@quitscope/discord-welcomecard 0.1.0
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/LICENSE +21 -0
- package/README.md +102 -0
- package/dist/OFL.txt +93 -0
- package/dist/Poppins-Bold.ttf +0 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/discord.cjs +34 -0
- package/dist/discord.cjs.map +1 -0
- package/dist/discord.d.cts +5 -0
- package/dist/discord.d.ts +5 -0
- package/dist/discord.js +11 -0
- package/dist/discord.js.map +1 -0
- package/dist/index.cjs +755 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +45 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +727 -0
- package/dist/index.js.map +1 -0
- package/dist/register.ts +21 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/assets/fonts/register.ts","../src/presets/centered.ts","../src/presets/neon.ts","../src/presets/minimal.ts","../src/presets/hero.ts","../src/presets/index.ts","../src/errors.ts","../src/render/toPNG.ts","../src/render/layout.ts","../src/assets/loadImage.ts","../src/render/drawFrame.ts","../src/render/toGIF.ts","../node_modules/.pnpm/gifenc@1.0.3/node_modules/gifenc/src/constants.js","../node_modules/.pnpm/gifenc@1.0.3/node_modules/gifenc/src/stream.js","../node_modules/.pnpm/gifenc@1.0.3/node_modules/gifenc/src/lzwEncode.js","../node_modules/.pnpm/gifenc@1.0.3/node_modules/gifenc/src/rgb-packing.js","../node_modules/.pnpm/gifenc@1.0.3/node_modules/gifenc/src/pnnquant2.js","../node_modules/.pnpm/gifenc@1.0.3/node_modules/gifenc/src/color.js","../node_modules/.pnpm/gifenc@1.0.3/node_modules/gifenc/src/palettize.js","../node_modules/.pnpm/gifenc@1.0.3/node_modules/gifenc/src/index.js","../src/animate/text.ts","../src/animate/avatar.ts","../src/animate/background.ts","../src/animate/index.ts","../src/WelcomeCard.ts"],"sourcesContent":["import type { CardOptions } from './types.js';\n\nexport const CARD_WIDTH = 1024;\nexport const CARD_HEIGHT = 384; // ~16:6 banner\n\nexport const GIF_FRAMES = 30;\nexport const GIF_DELAY_MS = 50; // ~20fps\nexport const GIF_SCALE = 0.5; // GIFs render at half size to stay under Discord upload limits\n\nexport const DEFAULT_OPTIONS: CardOptions = {\n preset: 'centered',\n theme: 'dark',\n font: {},\n animations: [],\n};\n","import { GlobalFonts } from '@napi-rs/canvas';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\nimport { existsSync } from 'node:fs';\n\nconst here = dirname(fileURLToPath(import.meta.url));\n\n// dev/tests run from src/assets/fonts; the published build runs from dist\n// with the font copied next to it (tsup publicDir).\nconst candidates = [\n join(here, 'Poppins-Bold.ttf'),\n join(here, 'assets', 'fonts', 'Poppins-Bold.ttf'),\n join(here, '..', 'src', 'assets', 'fonts', 'Poppins-Bold.ttf'),\n];\n\nconst fontPath = candidates.find(existsSync);\nif (fontPath) {\n GlobalFonts.registerFromPath(fontPath, 'WelcomeCard');\n}\n\nexport const DEFAULT_FONT_FAMILY = 'WelcomeCard';\n","import { CARD_WIDTH, CARD_HEIGHT } from '../constants.js';\nimport type { CardOptions, MemberCountPosition } from '../types.js';\nimport { DEFAULT_FONT_FAMILY } from '../assets/fonts/register.js';\n\nconst EDGE_PAD = 24;\nconst TOP_BASELINE = 36; // baseline y for top-anchored text\n\nexport function resolvePosition(\n position: MemberCountPosition | undefined,\n width: number,\n height: number,\n): { x: number; y: number; align: 'left' | 'center' | 'right' } {\n const pos = position === undefined || position === 'corner' ? 'bottom-right' : position;\n const [v, h] = pos === 'center' ? ['center', 'center'] : pos.split('-');\n return {\n x: h === 'left' ? EDGE_PAD : h === 'center' ? width / 2 : width - EDGE_PAD,\n y: v === 'top' ? TOP_BASELINE : v === 'center' ? height / 2 : height - EDGE_PAD,\n align: h as 'left' | 'center' | 'right',\n };\n}\n\nexport interface TextBox {\n text: string;\n x: number;\n y: number;\n size: number;\n color: string;\n family: string;\n align: 'left' | 'center' | 'right';\n}\n\nexport interface LayoutResult {\n width: number;\n height: number;\n backgroundColor: string;\n background?: string | Buffer;\n avatar: { x: number; y: number; size: number; ringColor: string; source?: string | Buffer };\n username: TextBox;\n subtitle?: TextBox;\n memberCount?: TextBox;\n}\n\nexport function centeredLayout(opts: CardOptions): LayoutResult {\n const width = CARD_WIDTH;\n const height = CARD_HEIGHT;\n const accent = opts.theme === 'dark' ? '#89b4fa' : '#1e66f5';\n const bgColor =\n typeof opts.background === 'string' && opts.background.startsWith('#')\n ? opts.background\n : opts.theme === 'dark'\n ? '#1e1e2e'\n : '#eff1f5';\n const textColor = opts.font.color ?? (opts.theme === 'dark' ? '#ffffff' : '#11111b');\n const family = opts.font.family ?? DEFAULT_FONT_FAMILY;\n\n const avatarSize = 120;\n const avatarY = 50;\n\n return {\n width,\n height,\n backgroundColor: bgColor,\n background:\n typeof opts.background === 'string' && opts.background.startsWith('#')\n ? undefined\n : opts.background,\n avatar: {\n x: width / 2 - avatarSize / 2,\n y: avatarY,\n size: avatarSize,\n ringColor: accent,\n source: opts.avatar,\n },\n username: {\n text: opts.username ?? '',\n x: width / 2,\n y: avatarY + avatarSize + 60,\n size: opts.font.size ?? 44,\n color: textColor,\n family,\n align: 'center',\n },\n subtitle: opts.subtitle\n ? {\n text: opts.subtitle,\n x: width / 2,\n y: avatarY + avatarSize + 105,\n size: 24,\n color: textColor,\n family,\n align: 'center',\n }\n : undefined,\n memberCount:\n opts.memberCount !== undefined\n ? {\n text: `MEMBER #${opts.memberCount}`,\n // centered preset: everything centered by default, count included\n ...resolvePosition(opts.memberCountPosition ?? 'bottom-center', width, height),\n size: 16,\n color: textColor,\n family,\n }\n : undefined,\n };\n}\n","import { centeredLayout } from './centered.js';\nimport type { CardOptions } from '../types.js';\nimport type { LayoutResult } from './centered.js';\n\nexport function neonLayout(opts: CardOptions): LayoutResult {\n const base = centeredLayout(opts);\n return {\n ...base,\n backgroundColor: opts.background?.startsWith('#') ? opts.background : '#0b0b1a',\n avatar: { ...base.avatar, ringColor: '#00ffd5' },\n username: { ...base.username, color: opts.font.color ?? '#00ffd5' },\n };\n}\n","import { centeredLayout } from './centered.js';\nimport type { CardOptions } from '../types.js';\nimport type { LayoutResult } from './centered.js';\n\nexport function minimalLayout(opts: CardOptions): LayoutResult {\n const base = centeredLayout(opts);\n return {\n ...base,\n backgroundColor: opts.background?.startsWith('#') ? opts.background : '#ffffff',\n avatar: { ...base.avatar, ringColor: '#222222' },\n username: { ...base.username, color: opts.font.color ?? '#111111' },\n subtitle: base.subtitle ? { ...base.subtitle, color: '#555555' } : undefined,\n };\n}\n","import { centeredLayout, resolvePosition } from './centered.js';\nimport type { CardOptions } from '../types.js';\nimport type { LayoutResult } from './centered.js';\n\n// Hero: avatar shifted left, text left-aligned beside it.\nexport function heroLayout(opts: CardOptions): LayoutResult {\n const base = centeredLayout(opts);\n const avatarX = 60;\n const textX = avatarX + base.avatar.size + 40;\n return {\n ...base,\n backgroundColor: opts.background?.startsWith('#') ? opts.background : '#101830',\n avatar: { ...base.avatar, x: avatarX, y: base.height / 2 - base.avatar.size / 2 },\n username: { ...base.username, x: textX, y: base.height / 2 - 6, align: 'left' },\n subtitle: base.subtitle\n ? { ...base.subtitle, x: textX, y: base.height / 2 + 30, align: 'left' }\n : undefined,\n memberCount: base.memberCount\n ? // hero is asymmetric — default the count to the corner, not bottom-center\n {\n ...base.memberCount,\n ...resolvePosition(opts.memberCountPosition ?? 'bottom-right', base.width, base.height),\n }\n : undefined,\n };\n}\n","import type { CardOptions, PresetName } from '../types.js';\nimport { centeredLayout, type LayoutResult } from './centered.js';\nimport { neonLayout } from './neon.js';\nimport { minimalLayout } from './minimal.js';\nimport { heroLayout } from './hero.js';\n\nexport type { LayoutResult, TextBox } from './centered.js';\nexport type LayoutFn = (opts: CardOptions) => LayoutResult;\n\nexport const PRESETS: Record<PresetName, LayoutFn> = {\n centered: centeredLayout,\n neon: neonLayout,\n minimal: minimalLayout,\n hero: heroLayout,\n};\n","export class WelcomeCardError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WelcomeCardError';\n }\n}\n","import { createCanvas } from '@napi-rs/canvas';\nimport '../assets/fonts/register.js';\nimport type { CardOptions } from '../types.js';\nimport { layout } from './layout.js';\nimport { drawFrame, STATIC_FRAME } from './drawFrame.js';\n\nexport async function renderPNG(opts: CardOptions): Promise<Buffer> {\n const l = layout(opts);\n const canvas = createCanvas(l.width, l.height);\n const ctx = canvas.getContext('2d');\n await drawFrame(ctx, l, STATIC_FRAME);\n return canvas.toBuffer('image/png');\n}\n","import type { CardOptions } from '../types.js';\nimport { PRESETS, type LayoutResult } from '../presets/index.js';\nimport { WelcomeCardError } from '../errors.js';\n\nexport function layout(opts: CardOptions): LayoutResult {\n const fn = PRESETS[opts.preset];\n if (!fn) {\n throw new WelcomeCardError(\n `Unknown preset \"${opts.preset}\". Allowed: ${Object.keys(PRESETS).join(', ')}`,\n );\n }\n return fn(opts);\n}\n","import { loadImage, createCanvas, type Image } from '@napi-rs/canvas';\n\nasync function solidImage(color: string, w: number, h: number): Promise<Image> {\n const canvas = createCanvas(w, h);\n const ctx = canvas.getContext('2d');\n ctx.fillStyle = color;\n ctx.fillRect(0, 0, w, h);\n return loadImage(canvas.toBuffer('image/png'));\n}\n\n// Cache so GIF rendering (N frames) fetches each URL/Buffer only once.\nconst cache = new Map<string | Buffer, Image>();\n\nexport async function loadImageOrFallback(\n source: string | Buffer | undefined,\n fallbackColor: string,\n w = 256,\n h = 256,\n): Promise<Image> {\n if (source === undefined) return solidImage(fallbackColor, w, h);\n const hit = cache.get(source);\n if (hit) return hit;\n try {\n const img = await loadImage(source);\n cache.set(source, img);\n return img;\n } catch {\n return solidImage(fallbackColor, w, h);\n }\n}\n","import type { SKRSContext2D } from '@napi-rs/canvas';\nimport type { LayoutResult, TextBox } from '../presets/index.js';\nimport { loadImageOrFallback } from '../assets/loadImage.js';\n\nexport interface FrameState {\n textAlpha: number; // 0..1 reveal for text\n avatarGlow: number; // 0..1 glow intensity\n backgroundShift: number; // 0..1 gradient phase\n}\n\nexport const STATIC_FRAME: FrameState = { textAlpha: 1, avatarGlow: 1, backgroundShift: 0 };\n\nfunction drawText(ctx: SKRSContext2D, box: TextBox, alpha: number) {\n ctx.save();\n ctx.globalAlpha = alpha;\n ctx.fillStyle = box.color;\n ctx.textAlign = box.align;\n ctx.textBaseline = 'alphabetic';\n ctx.font = `${box.size}px ${box.family}`;\n ctx.fillText(box.text, box.x, box.y);\n ctx.restore();\n}\n\nexport async function drawFrame(\n ctx: SKRSContext2D,\n l: LayoutResult,\n state: FrameState,\n): Promise<void> {\n // background\n ctx.fillStyle = l.backgroundColor;\n ctx.fillRect(0, 0, l.width, l.height);\n if (l.background !== undefined) {\n const bg = await loadImageOrFallback(l.background, l.backgroundColor, l.width, l.height);\n ctx.drawImage(bg, 0, 0, l.width, l.height);\n }\n if (state.backgroundShift > 0) {\n // diagonal sheen sliding across the card; phase 0..1 loops with the GIF\n const x = (state.backgroundShift * 2 - 1) * l.width * 2;\n const g = ctx.createLinearGradient(x, 0, x + l.width, l.height);\n g.addColorStop(0, 'rgba(255,255,255,0)');\n g.addColorStop(0.5, 'rgba(255,255,255,0.10)');\n g.addColorStop(1, 'rgba(255,255,255,0)');\n ctx.fillStyle = g;\n ctx.fillRect(0, 0, l.width, l.height);\n }\n\n // avatar (circular) with glow ring\n const { x, y, size, ringColor } = l.avatar;\n const cx = x + size / 2;\n const cy = y + size / 2;\n ctx.save();\n ctx.shadowColor = ringColor;\n ctx.shadowBlur = 10 + state.avatarGlow * 25;\n ctx.lineWidth = 6;\n ctx.strokeStyle = ringColor;\n ctx.beginPath();\n ctx.arc(cx, cy, size / 2 + 3, 0, Math.PI * 2);\n ctx.stroke();\n ctx.restore();\n\n const avatarImg = await loadImageOrFallback(l.avatar.source, ringColor, size, size);\n ctx.save();\n ctx.beginPath();\n ctx.arc(cx, cy, size / 2, 0, Math.PI * 2);\n ctx.clip();\n ctx.drawImage(avatarImg, x, y, size, size);\n ctx.restore();\n\n // text\n drawText(ctx, l.username, state.textAlpha);\n if (l.subtitle) drawText(ctx, l.subtitle, state.textAlpha);\n if (l.memberCount) drawText(ctx, l.memberCount, state.textAlpha);\n}\n","import { createCanvas } from '@napi-rs/canvas';\nimport * as gifencMod from 'gifenc';\n// gifenc ships dual CJS/ESM with inconsistent interop — named exports may live on the\n// namespace (vite/bundlers) or behind .default (node CJS-ESM interop). Pick whichever has them.\ntype Gifenc = typeof import('gifenc');\nconst { GIFEncoder, quantize, applyPalette } =\n 'GIFEncoder' in gifencMod ? (gifencMod as Gifenc) : (gifencMod as { default: Gifenc }).default;\nimport '../assets/fonts/register.js';\nimport type { CardOptions } from '../types.js';\nimport { GIF_FRAMES, GIF_DELAY_MS, GIF_SCALE } from '../constants.js';\nimport { layout } from './layout.js';\nimport { drawFrame } from './drawFrame.js';\nimport { frameStateFor } from '../animate/index.js';\n\nexport async function renderGIF(opts: CardOptions): Promise<Buffer> {\n const l = layout(opts);\n // draw at full size, encode at half size: smaller files, under Discord limits\n const canvas = createCanvas(l.width, l.height);\n const ctx = canvas.getContext('2d');\n const gw = Math.round(l.width * GIF_SCALE);\n const gh = Math.round(l.height * GIF_SCALE);\n const out = createCanvas(gw, gh);\n const outCtx = out.getContext('2d');\n const enc = GIFEncoder();\n\n const frames = opts.animations.length === 0 ? 1 : GIF_FRAMES;\n // one shared palette for all frames: stable colors (no flicker), faster encode\n let palette: number[][] | undefined;\n for (let i = 0; i < frames; i++) {\n const progress = frames === 1 ? 0 : i / frames;\n const state = frameStateFor(opts.animations, progress);\n await drawFrame(ctx, l, state);\n outCtx.drawImage(canvas, 0, 0, gw, gh);\n const { data } = outCtx.getImageData(0, 0, gw, gh);\n palette ??= quantize(data, 256);\n const index = applyPalette(data, palette);\n enc.writeFrame(index, gw, gh, { palette, delay: GIF_DELAY_MS });\n }\n enc.finish();\n return Buffer.from(enc.bytes());\n}\n","export default {\n signature: \"GIF\",\n version: \"89a\",\n trailer: 0x3B,\n extensionIntroducer: 0x21,\n applicationExtensionLabel: 0xFF,\n graphicControlExtensionLabel: 0xF9,\n imageSeparator: 0x2C,\n // Header\n signatureSize: 3,\n versionSize: 3,\n globalColorTableFlagMask: 0b10000000,\n colorResolutionMask: 0b01110000,\n sortFlagMask: 0b00001000,\n globalColorTableSizeMask: 0b00000111,\n // Application extension\n applicationIdentifierSize: 8,\n applicationAuthCodeSize: 3,\n // Graphic control extension\n disposalMethodMask: 0b00011100,\n userInputFlagMask: 0b00000010,\n transparentColorFlagMask: 0b00000001,\n // Image descriptor\n localColorTableFlagMask: 0b10000000,\n interlaceFlagMask: 0b01000000,\n idSortFlagMask: 0b00100000,\n localColorTableSizeMask: 0b00000111\n}\n","export default function createStream(initialCapacity = 256) {\n let cursor = 0;\n let contents = new Uint8Array(initialCapacity);\n\n return {\n get buffer() {\n return contents.buffer;\n },\n reset() {\n cursor = 0;\n },\n bytesView() {\n return contents.subarray(0, cursor);\n },\n bytes() {\n return contents.slice(0, cursor);\n },\n writeByte(byte) {\n expand(cursor + 1);\n contents[cursor] = byte;\n cursor++;\n },\n writeBytes(data, offset = 0, byteLength = data.length) {\n expand(cursor + byteLength);\n for (let i = 0; i < byteLength; i++) {\n contents[cursor++] = data[i + offset];\n }\n },\n writeBytesView(data, offset = 0, byteLength = data.byteLength) {\n expand(cursor + byteLength);\n contents.set(data.subarray(offset, offset + byteLength), cursor);\n cursor += byteLength;\n },\n };\n\n function expand(newCapacity) {\n var prevCapacity = contents.length;\n if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.\n // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.\n // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to\n // avoid overshooting the allocation cap by a very large margin.\n var CAPACITY_DOUBLING_MAX = 1024 * 1024;\n newCapacity = Math.max(\n newCapacity,\n (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>>\n 0\n );\n if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.\n const oldContents = contents;\n contents = new Uint8Array(newCapacity); // Allocate new storage.\n if (cursor > 0) contents.set(oldContents.subarray(0, cursor), 0);\n }\n}\n","/*\n LZWEncoder.js\n Authors\n Kevin Weiner (original Java version - kweiner@fmsware.com)\n Thibault Imbert (AS3 version - bytearray.org)\n Johan Nordberg (JS version - code@johan-nordberg.com)\n Acknowledgements\n GIFCOMPR.C - GIF Image compression routines\n Lempel-Ziv compression based on 'compress'. GIF modifications by\n David Rowley (mgardi@watdcsu.waterloo.edu)\n GIF Image compression - modified 'compress'\n Based on: compress.c - File compression ala IEEE Computer, June 1984.\n By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)\n Jim McKie (decvax!mcvax!jim)\n Steve Davies (decvax!vax135!petsd!peora!srd)\n Ken Turkowski (decvax!decwrl!turtlevax!ken)\n James A. Woods (decvax!ihnp4!ames!jaw)\n Joe Orost (decvax!vax135!petsd!joe)\n Matt DesLauriers (@mattdesl - V8/JS optimizations)\n Mathieu Henri (@p01 - JS optimization)\n*/\n\nimport createStream from \"./stream.js\";\n\nconst EOF = -1;\nconst BITS = 12;\nconst DEFAULT_HSIZE = 5003; // 80% occupancy\nconst MASKS = [\n 0x0000,\n 0x0001,\n 0x0003,\n 0x0007,\n 0x000f,\n 0x001f,\n 0x003f,\n 0x007f,\n 0x00ff,\n 0x01ff,\n 0x03ff,\n 0x07ff,\n 0x0fff,\n 0x1fff,\n 0x3fff,\n 0x7fff,\n 0xffff,\n];\n\nfunction lzwEncode(\n width,\n height,\n pixels,\n colorDepth,\n outStream = createStream(512),\n accum = new Uint8Array(256),\n htab = new Int32Array(DEFAULT_HSIZE),\n codetab = new Int32Array(DEFAULT_HSIZE)\n) {\n const hsize = htab.length;\n const initCodeSize = Math.max(2, colorDepth);\n\n accum.fill(0);\n codetab.fill(0);\n htab.fill(-1);\n\n let cur_accum = 0;\n let cur_bits = 0;\n\n // Algorithm: use open addressing double hashing (no chaining) on the\n // prefix code / next character combination. We do a variant of Knuth's\n // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime\n // secondary probe. Here, the modular division first probe is gives way\n // to a faster exclusive-or manipulation. Also do block compression with\n // an adaptive reset, whereby the code table is cleared when the compression\n // ratio decreases, but after the table fills. The variable-length output\n // codes are re-sized at this point, and a special CLEAR code is generated\n // for the decompressor. Late addition: construct the table according to\n // file size for noticeable speed improvement on small files. Please direct\n // questions about this implementation to ames!jaw.\n\n // compress and write the pixel data\n const init_bits = initCodeSize + 1;\n\n // Set up the globals: g_init_bits - initial number of bits\n const g_init_bits = init_bits;\n\n // Set up the necessary values\n\n // block compression parameters -- after all codes are used up,\n // and compression rate changes, start over.\n let clear_flg = false;\n let n_bits = g_init_bits;\n let maxcode = (1 << n_bits) - 1;\n\n const ClearCode = 1 << (init_bits - 1);\n const EOFCode = ClearCode + 1;\n let free_ent = ClearCode + 2;\n let a_count = 0; // clear packet\n\n let ent = pixels[0];\n\n let hshift = 0;\n for (let fcode = hsize; fcode < 65536; fcode *= 2) {\n ++hshift;\n }\n hshift = 8 - hshift; // set hash code range bound\n\n outStream.writeByte(initCodeSize); // write \"initial code size\" byte\n\n output(ClearCode);\n\n const length = pixels.length;\n for (let idx = 1; idx < length; idx++) {\n next_block: {\n const c = pixels[idx];\n const fcode = (c << BITS) + ent;\n let i = (c << hshift) ^ ent; // xor hashing\n if (htab[i] === fcode) {\n ent = codetab[i];\n break next_block;\n }\n\n const disp = i === 0 ? 1 : hsize - i; // secondary hash (after G. Knott)\n while (htab[i] >= 0) {\n // non-empty slot\n i -= disp;\n if (i < 0) i += hsize;\n if (htab[i] === fcode) {\n ent = codetab[i];\n break next_block;\n }\n }\n output(ent);\n ent = c;\n if (free_ent < 1 << BITS) {\n codetab[i] = free_ent++; // code -> hashtable\n htab[i] = fcode;\n } else {\n // Clear out the hash table\n // table clear for block compress\n htab.fill(-1);\n free_ent = ClearCode + 2;\n clear_flg = true;\n output(ClearCode);\n }\n }\n }\n\n // Put out the final code.\n output(ent);\n output(EOFCode);\n\n outStream.writeByte(0); // write block terminator\n return outStream.bytesView();\n\n function output(code) {\n cur_accum &= MASKS[cur_bits];\n\n if (cur_bits > 0) cur_accum |= code << cur_bits;\n else cur_accum = code;\n\n cur_bits += n_bits;\n\n while (cur_bits >= 8) {\n // Add a character to the end of the current packet, and if it is 254\n // characters, flush the packet to disk.\n accum[a_count++] = cur_accum & 0xff;\n if (a_count >= 254) {\n outStream.writeByte(a_count);\n outStream.writeBytesView(accum, 0, a_count);\n a_count = 0;\n }\n cur_accum >>= 8;\n cur_bits -= 8;\n }\n\n // If the next entry is going to be too big for the code size,\n // then increase it, if possible.\n if (free_ent > maxcode || clear_flg) {\n if (clear_flg) {\n n_bits = g_init_bits;\n maxcode = (1 << n_bits) - 1;\n clear_flg = false;\n } else {\n ++n_bits;\n maxcode = n_bits === BITS ? (1 << n_bits) : (1 << n_bits) - 1;\n }\n }\n\n if (code == EOFCode) {\n // At EOF, write the rest of the buffer.\n while (cur_bits > 0) {\n // Add a character to the end of the current packet, and if it is 254\n // characters, flush the packet to disk.\n accum[a_count++] = cur_accum & 0xff;\n if (a_count >= 254) {\n outStream.writeByte(a_count);\n outStream.writeBytesView(accum, 0, a_count);\n a_count = 0;\n }\n cur_accum >>= 8;\n cur_bits -= 8;\n }\n // Flush the packet to disk, and reset the accumulator\n if (a_count > 0) {\n outStream.writeByte(a_count);\n outStream.writeBytesView(accum, 0, a_count);\n a_count = 0;\n }\n }\n }\n}\n\nexport default lzwEncode;\n","export function uint32_to_rgba(color) {\n var a = (color >> 24) & 0xff;\n var b = (color >> 16) & 0xff;\n var g = (color >> 8) & 0xff;\n var r = color & 0xff;\n return [r, g, b, a];\n}\n\nexport function rgba_to_uint32(r, g, b, a) {\n return (a << 24) | (b << 16) | (g << 8) | r;\n}\n\nexport function rgb888_to_rgb565(r, g, b) {\n return ((r << 8) & 0xf800) | ((g << 2) & 0x03e0) | (b >> 3);\n}\n\nexport function rgba8888_to_rgba4444(r, g, b, a) {\n return (r >> 4) | (g & 0xf0) | ((b & 0xf0) << 4) | ((a & 0xf0) << 8);\n}\n\nexport function rgb888_to_rgb444(r, g, b) {\n return ((r >> 4) << 8) | (g & 0xf0) | (b >> 4);\n}\n\n// Alternative 565 ?\n// return ((r & 0xf8) << 8) + ((g & 0xfc) << 3) + (b >> 3);\n\n// Alternative 4444 ?\n// ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | (g & 0xf0) | (b >> 4);\n","// Modified from:\n// https://github.com/mcychan/PnnQuant.js/blob/master/src/pnnquant.js\n\n/* Fast pairwise nearest neighbor based algorithm for multilevel thresholding\nCopyright (C) 2004-2019 Mark Tyler and Dmitry Groshev\nCopyright (c) 2018-2021 Miller Cy Chan\n* error measure; time used is proportional to number of bins squared - WJ */\n\nimport {\n rgb888_to_rgb565,\n rgb888_to_rgb444,\n rgba8888_to_rgba4444,\n} from \"./rgb-packing.js\";\n\nfunction clamp(value, min, max) {\n return value < min ? min : value > max ? max : value;\n}\n\nfunction sqr(value) {\n return value * value;\n}\n\nfunction find_nn(bins, idx, hasAlpha) {\n var nn = 0;\n var err = 1e100;\n\n const bin1 = bins[idx];\n const n1 = bin1.cnt;\n const wa = bin1.ac;\n const wr = bin1.rc;\n const wg = bin1.gc;\n const wb = bin1.bc;\n for (var i = bin1.fw; i != 0; i = bins[i].fw) {\n const bin = bins[i];\n const n2 = bin.cnt;\n const nerr2 = (n1 * n2) / (n1 + n2);\n if (nerr2 >= err) continue;\n\n var nerr = 0;\n if (hasAlpha) {\n nerr += nerr2 * sqr(bin.ac - wa);\n if (nerr >= err) continue;\n }\n\n nerr += nerr2 * sqr(bin.rc - wr);\n if (nerr >= err) continue;\n\n nerr += nerr2 * sqr(bin.gc - wg);\n if (nerr >= err) continue;\n\n nerr += nerr2 * sqr(bin.bc - wb);\n if (nerr >= err) continue;\n err = nerr;\n nn = i;\n }\n bin1.err = err;\n bin1.nn = nn;\n}\n\nfunction create_bin() {\n return {\n ac: 0,\n rc: 0,\n gc: 0,\n bc: 0,\n cnt: 0,\n nn: 0,\n fw: 0,\n bk: 0,\n tm: 0,\n mtm: 0,\n err: 0,\n };\n}\n\nfunction bin_add_rgb(bin, r, g, b) {\n bin.rc += r;\n bin.gc += g;\n bin.bc += b;\n bin.cnt++;\n}\n\nfunction create_bin_list(data, format) {\n const bincount = format === \"rgb444\" ? 4096 : 65536;\n const bins = new Array(bincount);\n const size = data.length;\n\n /* Build histogram */\n // Note: Instead of introducing branching/conditions\n // within a very hot per-pixel iteration, we just duplicate the code\n // for each new condition\n if (format === \"rgba4444\") {\n for (let i = 0; i < size; ++i) {\n const color = data[i];\n const a = (color >> 24) & 0xff;\n const b = (color >> 16) & 0xff;\n const g = (color >> 8) & 0xff;\n const r = color & 0xff;\n\n // reduce to rgb4444 16-bit uint\n const index = rgba8888_to_rgba4444(r, g, b, a);\n let bin = index in bins ? bins[index] : (bins[index] = create_bin());\n bin.rc += r;\n bin.gc += g;\n bin.bc += b;\n bin.ac += a;\n bin.cnt++;\n }\n }\n \n else if (format === \"rgb444\") {\n for (let i = 0; i < size; ++i) {\n const color = data[i];\n const b = (color >> 16) & 0xff;\n const g = (color >> 8) & 0xff;\n const r = color & 0xff;\n\n // reduce to rgb444 12-bit uint\n const index = rgb888_to_rgb444(r, g, b);\n let bin = index in bins ? bins[index] : (bins[index] = create_bin());\n bin.rc += r;\n bin.gc += g;\n bin.bc += b;\n bin.cnt++;\n }\n } else {\n for (let i = 0; i < size; ++i) {\n const color = data[i];\n const b = (color >> 16) & 0xff;\n const g = (color >> 8) & 0xff;\n const r = color & 0xff;\n\n // reduce to rgb565 16-bit uint\n const index = rgb888_to_rgb565(r, g, b);\n let bin = index in bins ? bins[index] : (bins[index] = create_bin());\n bin.rc += r;\n bin.gc += g;\n bin.bc += b;\n bin.cnt++;\n }\n }\n return bins;\n}\n\nexport default function quantize(rgba, maxColors, opts = {}) {\n const {\n format = \"rgb565\",\n clearAlpha = true,\n clearAlphaColor = 0x00,\n clearAlphaThreshold = 0,\n oneBitAlpha = false,\n } = opts;\n\n if (!rgba || !rgba.buffer) {\n throw new Error('quantize() expected RGBA Uint8Array data');\n }\n if (!(rgba instanceof Uint8Array) && !(rgba instanceof Uint8ClampedArray)) {\n throw new Error('quantize() expected RGBA Uint8Array data');\n }\n \n const data = new Uint32Array(rgba.buffer);\n\n let useSqrt = opts.useSqrt !== false;\n\n // format can be:\n // rgb565 (default)\n // rgb444\n // rgba4444\n\n const hasAlpha = format === \"rgba4444\";\n const bins = create_bin_list(data, format);\n const bincount = bins.length;\n const bincountMinusOne = bincount - 1;\n const heap = new Uint32Array(bincount + 1);\n\n /* Cluster nonempty bins at one end of array */\n var maxbins = 0;\n for (var i = 0; i < bincount; ++i) {\n const bin = bins[i];\n if (bin != null) {\n var d = 1.0 / bin.cnt;\n if (hasAlpha) bin.ac *= d;\n bin.rc *= d;\n bin.gc *= d;\n bin.bc *= d;\n bins[maxbins++] = bin;\n }\n }\n\n if (sqr(maxColors) / maxbins < 0.022) {\n useSqrt = false;\n }\n\n var i = 0;\n for (; i < maxbins - 1; ++i) {\n bins[i].fw = i + 1;\n bins[i + 1].bk = i;\n if (useSqrt) bins[i].cnt = Math.sqrt(bins[i].cnt);\n }\n if (useSqrt) bins[i].cnt = Math.sqrt(bins[i].cnt);\n\n var h, l, l2;\n /* Initialize nearest neighbors and build heap of them */\n for (i = 0; i < maxbins; ++i) {\n find_nn(bins, i, false);\n /* Push slot on heap */\n var err = bins[i].err;\n for (l = ++heap[0]; l > 1; l = l2) {\n l2 = l >> 1;\n if (bins[(h = heap[l2])].err <= err) break;\n heap[l] = h;\n }\n heap[l] = i;\n }\n\n /* Merge bins which increase error the least */\n var extbins = maxbins - maxColors;\n for (i = 0; i < extbins; ) {\n var tb;\n /* Use heap to find which bins to merge */\n for (;;) {\n var b1 = heap[1];\n tb = bins[b1]; /* One with least error */\n /* Is stored error up to date? */\n if (tb.tm >= tb.mtm && bins[tb.nn].mtm <= tb.tm) break;\n if (tb.mtm == bincountMinusOne)\n /* Deleted node */ b1 = heap[1] = heap[heap[0]--];\n /* Too old error value */ else {\n find_nn(bins, b1, false);\n tb.tm = i;\n }\n /* Push slot down */\n var err = bins[b1].err;\n for (l = 1; (l2 = l + l) <= heap[0]; l = l2) {\n if (l2 < heap[0] && bins[heap[l2]].err > bins[heap[l2 + 1]].err) l2++;\n if (err <= bins[(h = heap[l2])].err) break;\n heap[l] = h;\n }\n heap[l] = b1;\n }\n\n /* Do a merge */\n var nb = bins[tb.nn];\n var n1 = tb.cnt;\n var n2 = nb.cnt;\n var d = 1.0 / (n1 + n2);\n if (hasAlpha) tb.ac = d * (n1 * tb.ac + n2 * nb.ac);\n tb.rc = d * (n1 * tb.rc + n2 * nb.rc);\n tb.gc = d * (n1 * tb.gc + n2 * nb.gc);\n tb.bc = d * (n1 * tb.bc + n2 * nb.bc);\n tb.cnt += nb.cnt;\n tb.mtm = ++i;\n\n /* Unchain deleted bin */\n bins[nb.bk].fw = nb.fw;\n bins[nb.fw].bk = nb.bk;\n nb.mtm = bincountMinusOne;\n }\n\n // let palette = new Uint32Array(maxColors);\n let palette = [];\n\n /* Fill palette */\n var k = 0;\n for (i = 0; ; ++k) {\n let r = clamp(Math.round(bins[i].rc), 0, 0xff);\n let g = clamp(Math.round(bins[i].gc), 0, 0xff);\n let b = clamp(Math.round(bins[i].bc), 0, 0xff);\n\n let a = 0xff;\n if (hasAlpha) {\n a = clamp(Math.round(bins[i].ac), 0, 0xff);\n if (oneBitAlpha) {\n const threshold = typeof oneBitAlpha === \"number\" ? oneBitAlpha : 127;\n a = a <= threshold ? 0x00 : 0xff;\n }\n if (clearAlpha && a <= clearAlphaThreshold) {\n r = g = b = clearAlphaColor;\n a = 0x00;\n }\n }\n\n const color = hasAlpha ? [r, g, b, a] : [r, g, b];\n const exists = existsInPalette(palette, color);\n if (!exists) palette.push(color);\n if ((i = bins[i].fw) == 0) break;\n }\n\n return palette;\n}\n\nfunction existsInPalette(palette, color) {\n for (let i = 0; i < palette.length; i++) {\n const p = palette[i];\n let matchesRGB =\n p[0] === color[0] && p[1] === color[1] && p[2] === color[2];\n let matchesAlpha =\n p.length >= 4 && color.length >= 4 ? p[3] === color[3] : true;\n if (matchesRGB && matchesAlpha) return true;\n }\n return false;\n}\n\n// TODO: Further 'clean' palette by merging nearly-identical colors?\n","function rgb2y(r, g, b) {\n return r * 0.29889531 + g * 0.58662247 + b * 0.11448223;\n}\nfunction rgb2i(r, g, b) {\n return r * 0.59597799 - g * 0.2741761 - b * 0.32180189;\n}\nfunction rgb2q(r, g, b) {\n return r * 0.21147017 - g * 0.52261711 + b * 0.31114694;\n}\n\nexport function colorDifferenceYIQSquared(yiqA, yiqB) {\n const y = yiqA[0] - yiqB[0];\n const i = yiqA[1] - yiqB[1];\n const q = yiqA[2] - yiqB[2];\n const a = alpha(yiqA) - alpha(yiqB);\n return y * y * 0.5053 + i * i * 0.299 + q * q * 0.1957 + a * a;\n}\n\nfunction alpha(array) {\n return array[3] != null ? array[3] : 0xff;\n}\n\nexport function colorDifferenceYIQ(yiqA, yiqB) {\n return Math.sqrt(colorDifferenceYIQSquared(yiqA, yiqB));\n}\n\nexport function colorDifferenceRGBToYIQSquared(rgb1, rgb2) {\n const [r1, g1, b1] = rgb1;\n const [r2, g2, b2] = rgb2;\n const y = rgb2y(r1, g1, b1) - rgb2y(r2, g2, b2),\n i = rgb2i(r1, g1, b1) - rgb2i(r2, g2, b2),\n q = rgb2q(r1, g1, b1) - rgb2q(r2, g2, b2);\n const a = alpha(rgb1) - alpha(rgb2);\n return y * y * 0.5053 + i * i * 0.299 + q * q * 0.1957 + a * a;\n}\n\nexport function colorDifferenceRGBToYIQ(rgb1, rgb2) {\n return Math.sqrt(colorDifferenceRGBToYIQSquared(rgb1, rgb2));\n}\n\nexport function euclideanDistanceSquared(a, b) {\n var sum = 0;\n var n;\n for (n = 0; n < a.length; n++) {\n const dx = a[n] - b[n];\n sum += dx * dx;\n }\n return sum;\n}\n\nexport function euclideanDistance(a, b) {\n return Math.sqrt(euclideanDistanceSquared(a, b));\n}\n","import {\n rgb888_to_rgb444,\n rgb888_to_rgb565,\n rgba8888_to_rgba4444,\n} from \"./rgb-packing.js\";\n\nimport { euclideanDistanceSquared } from \"./color.js\";\n\nfunction roundStep(byte, step) {\n return step > 1 ? Math.round(byte / step) * step : byte;\n}\n\nexport function prequantize(\n rgba,\n { roundRGB = 5, roundAlpha = 10, oneBitAlpha = null } = {}\n) {\n const data = new Uint32Array(rgba.buffer);\n for (let i = 0; i < data.length; i++) {\n const color = data[i];\n let a = (color >> 24) & 0xff;\n let b = (color >> 16) & 0xff;\n let g = (color >> 8) & 0xff;\n let r = color & 0xff;\n\n a = roundStep(a, roundAlpha);\n if (oneBitAlpha) {\n const threshold = typeof oneBitAlpha === \"number\" ? oneBitAlpha : 127;\n a = a <= threshold ? 0x00 : 0xff;\n }\n r = roundStep(r, roundRGB);\n g = roundStep(g, roundRGB);\n b = roundStep(b, roundRGB);\n\n data[i] = (a << 24) | (b << 16) | (g << 8) | (r << 0);\n }\n}\n\nexport function applyPalette(rgba, palette, format = \"rgb565\") {\n if (!rgba || !rgba.buffer) {\n throw new Error('quantize() expected RGBA Uint8Array data');\n }\n if (!(rgba instanceof Uint8Array) && !(rgba instanceof Uint8ClampedArray)) {\n throw new Error('quantize() expected RGBA Uint8Array data');\n }\n if (palette.length > 256) {\n throw new Error('applyPalette() only works with 256 colors or less');\n }\n\n const data = new Uint32Array(rgba.buffer);\n const length = data.length;\n const bincount = format === \"rgb444\" ? 4096 : 65536;\n const index = new Uint8Array(length);\n const cache = new Array(bincount);\n const hasAlpha = format === \"rgba4444\";\n\n // Some duplicate code below due to very hot code path\n // Introducing branching/conditions shows some significant impact\n if (format === \"rgba4444\") {\n for (let i = 0; i < length; i++) {\n const color = data[i];\n const a = (color >> 24) & 0xff;\n const b = (color >> 16) & 0xff;\n const g = (color >> 8) & 0xff;\n const r = color & 0xff;\n const key = rgba8888_to_rgba4444(r, g, b, a);\n const idx = key in cache ? cache[key] : (cache[key] = nearestColorIndexRGBA(r, g, b, a, palette));\n index[i] = idx;\n }\n } else {\n const rgb888_to_key = format === \"rgb444\" ? rgb888_to_rgb444 : rgb888_to_rgb565;\n for (let i = 0; i < length; i++) {\n const color = data[i];\n const b = (color >> 16) & 0xff;\n const g = (color >> 8) & 0xff;\n const r = color & 0xff;\n const key = rgb888_to_key(r, g, b);\n const idx = key in cache ? cache[key] : (cache[key] = nearestColorIndexRGB(r, g, b, palette));\n index[i] = idx;\n }\n }\n\n return index;\n}\n\nfunction nearestColorIndexRGBA(r, g, b, a, palette) {\n let k = 0;\n let mindist = 1e100;\n for (let i = 0; i < palette.length; i++) {\n const px2 = palette[i];\n const a2 = px2[3];\n let curdist = sqr(a2 - a);\n if (curdist > mindist) continue;\n const r2 = px2[0];\n curdist += sqr(r2 - r);\n if (curdist > mindist) continue;\n const g2 = px2[1];\n curdist += sqr(g2 - g);\n if (curdist > mindist) continue;\n const b2 = px2[2];\n curdist += sqr(b2 - b);\n if (curdist > mindist) continue;\n mindist = curdist;\n k = i;\n }\n return k;\n}\n\nfunction nearestColorIndexRGB(r, g, b, palette) {\n let k = 0;\n let mindist = 1e100;\n for (let i = 0; i < palette.length; i++) {\n const px2 = palette[i];\n const r2 = px2[0];\n let curdist = sqr(r2 - r);\n if (curdist > mindist) continue;\n const g2 = px2[1];\n curdist += sqr(g2 - g);\n if (curdist > mindist) continue;\n const b2 = px2[2];\n curdist += sqr(b2 - b);\n if (curdist > mindist) continue;\n mindist = curdist;\n k = i;\n }\n return k;\n}\n\nexport function snapColorsToPalette(palette, knownColors, threshold = 5) {\n if (!palette.length || !knownColors.length) return;\n\n const paletteRGB = palette.map((p) => p.slice(0, 3));\n const thresholdSq = threshold * threshold;\n const dim = palette[0].length;\n for (let i = 0; i < knownColors.length; i++) {\n let color = knownColors[i];\n if (color.length < dim) {\n // palette is RGBA, known is RGB\n color = [color[0], color[1], color[2], 0xff];\n } else if (color.length > dim) {\n // palette is RGB, known is RGBA\n color = color.slice(0, 3);\n } else {\n // make sure we always copy known colors\n color = color.slice();\n }\n const r = nearestColorIndexWithDistance(\n paletteRGB,\n color.slice(0, 3),\n euclideanDistanceSquared\n );\n const idx = r[0];\n const distanceSq = r[1];\n if (distanceSq > 0 && distanceSq <= thresholdSq) {\n palette[idx] = color;\n }\n }\n}\n\nfunction sqr(a) {\n return a * a;\n}\n\nexport function nearestColorIndex(\n colors,\n pixel,\n distanceFn = euclideanDistanceSquared\n) {\n let minDist = Infinity;\n let minDistIndex = -1;\n for (let j = 0; j < colors.length; j++) {\n const paletteColor = colors[j];\n const dist = distanceFn(pixel, paletteColor);\n if (dist < minDist) {\n minDist = dist;\n minDistIndex = j;\n }\n }\n return minDistIndex;\n}\n\nexport function nearestColorIndexWithDistance(\n colors,\n pixel,\n distanceFn = euclideanDistanceSquared\n) {\n let minDist = Infinity;\n let minDistIndex = -1;\n for (let j = 0; j < colors.length; j++) {\n const paletteColor = colors[j];\n const dist = distanceFn(pixel, paletteColor);\n if (dist < minDist) {\n minDist = dist;\n minDistIndex = j;\n }\n }\n return [minDistIndex, minDist];\n}\n\nexport function nearestColor(\n colors,\n pixel,\n distanceFn = euclideanDistanceSquared\n) {\n return colors[nearestColorIndex(colors, pixel, distanceFn)];\n}\n","import constants from \"./constants.js\";\nimport lzwEncode from \"./lzwEncode.js\";\nimport createStream from \"./stream.js\";\nimport quantize from \"./pnnquant2.js\";\n\nimport {\n prequantize,\n applyPalette,\n nearestColorIndex,\n nearestColor,\n nearestColorIndexWithDistance,\n snapColorsToPalette,\n} from \"./palettize.js\";\n\nfunction GIFEncoder(opt = {}) {\n const { initialCapacity = 4096, auto = true } = opt;\n\n // Stream all encoded data into this buffer\n const stream = createStream(initialCapacity);\n\n // Shared array data across all frames\n const HSIZE = 5003; // 80% occupancy\n const accum = new Uint8Array(256);\n const htab = new Int32Array(HSIZE);\n const codetab = new Int32Array(HSIZE);\n\n let hasInit = false;\n\n return {\n reset() {\n stream.reset();\n hasInit = false;\n },\n finish() {\n stream.writeByte(constants.trailer);\n },\n bytes() {\n return stream.bytes();\n },\n bytesView() {\n return stream.bytesView();\n },\n get buffer() {\n return stream.buffer;\n },\n get stream() {\n return stream;\n },\n writeHeader,\n writeFrame(index, width, height, opts = {}) {\n const {\n transparent = false,\n transparentIndex = 0x00,\n delay = 0,\n palette = null,\n repeat = 0, // -1=once, 0=forever, >0=count\n colorDepth = 8,\n dispose = -1,\n } = opts;\n\n let first = false;\n if (auto) {\n // In 'auto' mode, the first time we write a frame\n // we will write LSD/GCT/EXT\n if (!hasInit) {\n // have not yet init, we can consider this our first frame\n first = true;\n // in 'auto' mode, we also encode a header on first frame\n // this is different than manual mode where you must encode\n // header yoursef (or perhaps not write header altogether)\n writeHeader();\n hasInit = true;\n }\n } else {\n // in manual mode, the first frame is determined by the options only\n first = Boolean(opts.first);\n }\n\n width = Math.max(0, Math.floor(width));\n height = Math.max(0, Math.floor(height));\n\n // Write pre-frame details such as repeat count and global palette\n if (first) {\n if (!palette) {\n throw new Error(\"First frame must include a { palette } option\");\n }\n encodeLogicalScreenDescriptor(\n stream,\n width,\n height,\n palette,\n colorDepth\n );\n encodeColorTable(stream, palette);\n if (repeat >= 0) {\n encodeNetscapeExt(stream, repeat);\n }\n }\n\n const delayTime = Math.round(delay / 10);\n encodeGraphicControlExt(\n stream,\n dispose,\n delayTime,\n transparent,\n transparentIndex\n );\n\n const useLocalColorTable = Boolean(palette) && !first;\n encodeImageDescriptor(\n stream,\n width,\n height,\n useLocalColorTable ? palette : null\n );\n if (useLocalColorTable) encodeColorTable(stream, palette);\n encodePixels(\n stream,\n index,\n width,\n height,\n colorDepth,\n accum,\n htab,\n codetab\n );\n },\n };\n\n function writeHeader() {\n writeUTFBytes(stream, \"GIF89a\");\n }\n}\n\nfunction encodeGraphicControlExt(\n stream,\n dispose,\n delay,\n transparent,\n transparentIndex\n) {\n stream.writeByte(0x21); // extension introducer\n stream.writeByte(0xf9); // GCE label\n stream.writeByte(4); // data block size\n\n if (transparentIndex < 0) {\n transparentIndex = 0x00;\n transparent = false;\n }\n\n var transp, disp;\n if (!transparent) {\n transp = 0;\n disp = 0; // dispose = no action\n } else {\n transp = 1;\n disp = 2; // force clear if using transparent color\n }\n\n if (dispose >= 0) {\n disp = dispose & 7; // user override\n }\n\n disp <<= 2;\n\n const userInput = 0;\n\n // packed fields\n stream.writeByte(\n 0 | // 1:3 reserved\n disp | // 4:6 disposal\n userInput | // 7 user input - 0 = none\n transp // 8 transparency flag\n );\n\n writeUInt16(stream, delay); // delay x 1/100 sec\n stream.writeByte(transparentIndex || 0x00); // transparent color index\n stream.writeByte(0); // block terminator\n}\n\nfunction encodeLogicalScreenDescriptor(\n stream,\n width,\n height,\n palette,\n colorDepth = 8\n) {\n const globalColorTableFlag = 1;\n const sortFlag = 0;\n const globalColorTableSize = colorTableSize(palette.length) - 1;\n const fields =\n (globalColorTableFlag << 7) |\n ((colorDepth - 1) << 4) |\n (sortFlag << 3) |\n globalColorTableSize;\n const backgroundColorIndex = 0;\n const pixelAspectRatio = 0;\n writeUInt16(stream, width);\n writeUInt16(stream, height);\n stream.writeBytes([fields, backgroundColorIndex, pixelAspectRatio]);\n}\n\nfunction encodeNetscapeExt(stream, repeat) {\n stream.writeByte(0x21); // extension introducer\n stream.writeByte(0xff); // app extension label\n stream.writeByte(11); // block size\n writeUTFBytes(stream, \"NETSCAPE2.0\"); // app id + auth code\n stream.writeByte(3); // sub-block size\n stream.writeByte(1); // loop sub-block id\n writeUInt16(stream, repeat); // loop count (extra iterations, 0=repeat forever)\n stream.writeByte(0); // block terminator\n}\n\nfunction encodeColorTable(stream, palette) {\n const colorTableLength = 1 << colorTableSize(palette.length);\n for (let i = 0; i < colorTableLength; i++) {\n let color = [0, 0, 0];\n if (i < palette.length) {\n color = palette[i];\n }\n stream.writeByte(color[0]);\n stream.writeByte(color[1]);\n stream.writeByte(color[2]);\n }\n}\n\nfunction encodeImageDescriptor(stream, width, height, localPalette) {\n stream.writeByte(0x2c); // image separator\n\n writeUInt16(stream, 0); // x position\n writeUInt16(stream, 0); // y position\n writeUInt16(stream, width); // image size\n writeUInt16(stream, height);\n\n if (localPalette) {\n const interlace = 0;\n const sorted = 0;\n const palSize = colorTableSize(localPalette.length) - 1;\n // local palette\n stream.writeByte(\n 0x80 | // 1 local color table 1=yes\n interlace | // 2 interlace - 0=no\n sorted | // 3 sorted - 0=no\n 0 | // 4-5 reserved\n palSize // 6-8 size of color table\n );\n } else {\n // global palette\n stream.writeByte(0);\n }\n}\n\nfunction encodePixels(\n stream,\n index,\n width,\n height,\n colorDepth = 8,\n accum,\n htab,\n codetab\n) {\n lzwEncode(width, height, index, colorDepth, stream, accum, htab, codetab);\n}\n\n// Utilities\n\nfunction writeUInt16(stream, short) {\n stream.writeByte(short & 0xff);\n stream.writeByte((short >> 8) & 0xff);\n}\n\nfunction writeUTFBytes(stream, text) {\n for (var i = 0; i < text.length; i++) {\n stream.writeByte(text.charCodeAt(i));\n }\n}\n\nfunction colorTableSize(length) {\n return Math.max(Math.ceil(Math.log2(length)), 1);\n}\n\nexport {\n GIFEncoder,\n quantize,\n prequantize,\n applyPalette,\n nearestColorIndex,\n nearestColor,\n nearestColorIndexWithDistance,\n snapColorsToPalette,\n};\n\nexport default GIFEncoder;\n","// Ease-out reveal: alpha goes 0 -> 1 over first 70% of timeline.\nexport function textAlpha(progress: number): number {\n const p = Math.min(progress / 0.7, 1);\n return 1 - Math.pow(1 - p, 3);\n}\n","// Pulsing glow 0..1 using a sine wave over the loop.\nexport function avatarGlow(progress: number): number {\n return (Math.sin(progress * Math.PI * 2) + 1) / 2;\n}\n","// Phase 0..1 used by drawFrame to shift the background sheen.\nexport function backgroundShift(progress: number): number {\n return progress;\n}\n","import type { AnimationType } from '../types.js';\nimport type { FrameState } from '../render/drawFrame.js';\nimport { textAlpha } from './text.js';\nimport { avatarGlow } from './avatar.js';\nimport { backgroundShift } from './background.js';\n\nexport function frameStateFor(animations: AnimationType[], progress: number): FrameState {\n return {\n textAlpha: animations.includes('text') ? textAlpha(progress) : 1,\n avatarGlow: animations.includes('avatar') ? avatarGlow(progress) : 1,\n backgroundShift: animations.includes('background') ? backgroundShift(progress) : 0,\n };\n}\n","import type {\n AnimationType,\n CardOptions,\n FontOptions,\n MemberCountPosition,\n PresetName,\n Theme,\n} from './types.js';\nimport { DEFAULT_OPTIONS } from './constants.js';\nimport { PRESETS } from './presets/index.js';\nimport { WelcomeCardError } from './errors.js';\nimport { renderPNG } from './render/toPNG.js';\nimport { renderGIF } from './render/toGIF.js';\n\nexport class WelcomeCard {\n private opts: CardOptions = { ...DEFAULT_OPTIONS, font: {}, animations: [] };\n\n setPreset(preset: PresetName): this {\n if (!PRESETS[preset]) {\n throw new WelcomeCardError(\n `Unknown preset \"${preset}\". Allowed: ${Object.keys(PRESETS).join(', ')}`,\n );\n }\n this.opts.preset = preset;\n return this;\n }\n\n setUsername(username: string): this {\n this.opts.username = username;\n return this;\n }\n\n setAvatar(avatar: string | Buffer): this {\n this.opts.avatar = avatar;\n return this;\n }\n\n setSubtitle(subtitle: string): this {\n this.opts.subtitle = subtitle;\n return this;\n }\n\n setMemberCount(count: number): this {\n this.opts.memberCount = count;\n return this;\n }\n\n setMemberCountPosition(position: MemberCountPosition): this {\n this.opts.memberCountPosition = position;\n return this;\n }\n\n setBackground(background: string): this {\n this.opts.background = background;\n return this;\n }\n\n setTheme(theme: Theme): this {\n this.opts.theme = theme;\n return this;\n }\n\n setFont(font: FontOptions): this {\n this.opts.font = { ...this.opts.font, ...font };\n return this;\n }\n\n setAnimations(animations: AnimationType[]): this {\n this.opts.animations = animations;\n return this;\n }\n\n private validate(): void {\n if (!this.opts.username) {\n throw new WelcomeCardError('username is required — call .setUsername() before rendering.');\n }\n }\n\n async toPNG(): Promise<Buffer> {\n this.validate();\n return renderPNG(this.opts);\n }\n\n async toGIF(): Promise<Buffer> {\n this.validate();\n if (this.opts.animations.length === 0) {\n console.warn('[welcomecard] toGIF() called with no animations — output will be static.');\n }\n return renderGIF(this.opts);\n }\n}\n"],"mappings":"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","names":["createCanvas","x","createCanvas","createCanvas","createCanvas"]}
|
package/dist/register.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { GlobalFonts } from '@napi-rs/canvas';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
|
|
6
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
// dev/tests run from src/assets/fonts; the published build runs from dist
|
|
9
|
+
// with the font copied next to it (tsup publicDir).
|
|
10
|
+
const candidates = [
|
|
11
|
+
join(here, 'Poppins-Bold.ttf'),
|
|
12
|
+
join(here, 'assets', 'fonts', 'Poppins-Bold.ttf'),
|
|
13
|
+
join(here, '..', 'src', 'assets', 'fonts', 'Poppins-Bold.ttf'),
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const fontPath = candidates.find(existsSync);
|
|
17
|
+
if (fontPath) {
|
|
18
|
+
GlobalFonts.registerFromPath(fontPath, 'WelcomeCard');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const DEFAULT_FONT_FAMILY = 'WelcomeCard';
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@quitscope/discord-welcomecard",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Render Discord welcome cards as static PNG or animated GIF from one builder.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "QuitScope",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/QuitScope/discord-welcomecard.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/QuitScope/discord-welcomecard#readme",
|
|
12
|
+
"bugs": "https://github.com/QuitScope/discord-welcomecard/issues",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"discord",
|
|
15
|
+
"discord.js",
|
|
16
|
+
"welcome-card",
|
|
17
|
+
"welcome",
|
|
18
|
+
"canvas",
|
|
19
|
+
"gif",
|
|
20
|
+
"image-generation"
|
|
21
|
+
],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "./dist/index.cjs",
|
|
24
|
+
"module": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js",
|
|
30
|
+
"require": "./dist/index.cjs"
|
|
31
|
+
},
|
|
32
|
+
"./discord": {
|
|
33
|
+
"types": "./dist/discord.d.ts",
|
|
34
|
+
"import": "./dist/discord.js",
|
|
35
|
+
"require": "./dist/discord.cjs"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"files": ["dist"],
|
|
39
|
+
"engines": { "node": ">=18" },
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsup",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"test:watch": "vitest",
|
|
44
|
+
"examples": "node scripts/render-examples.mjs",
|
|
45
|
+
"prepublishOnly": "npm test && npm run build"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@napi-rs/canvas": "^0.1.65",
|
|
49
|
+
"gifenc": "^1.0.3"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"discord.js": "^14.0.0"
|
|
53
|
+
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"discord.js": { "optional": true }
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"discord.js": "^14.16.0",
|
|
59
|
+
"tsup": "^8.3.0",
|
|
60
|
+
"typescript": "^5.6.0",
|
|
61
|
+
"vitest": "^2.1.0"
|
|
62
|
+
}
|
|
63
|
+
}
|