{"_id":"better-discord-transcripts","_rev":"30-bea6537ee3ae0f72b6274c1bd3ca95b2","name":"better-discord-transcripts","dist-tags":{"latest":"2.0.0"},"versions":{"1.0.4":{"name":"better-discord-transcripts","version":"1.0.4","keywords":["discord","discord.js","transcript","html-transcript","discord-transcripts","discord-html-transcripts","components-v2","ticket","modmail"],"license":"Apache-2.0","_id":"better-discord-transcripts@1.0.4","maintainers":[{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"}],"homepage":"https://www.npmjs.com/package/better-discord-transcripts","dist":{"shasum":"a6d419f602723e1cf13d5b7370ad868ace16f7b2","tarball":"https://registry.npmjs.org/better-discord-transcripts/-/better-discord-transcripts-1.0.4.tgz","fileCount":47,"integrity":"sha512-RYYJJeLeeEl7uApb1noypQ2aBNVAD5Xk8/a2hkAJB/HTldonkEbvSKBc6WSa88ysdzHN1Q0VKAjRmOTJpy1UXw==","signatures":[{"sig":"MEYCIQCf6JU/Z78eBzzjX3E4Rs2OlJDx7Rn9H46U2ccqhNDnjAIhALLcDX8O0H2NmgyQfRVzkFXFGzxz1NaO25efmptQOJOa","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":220637},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js","require":"./dist/index.js"}},"scripts":{"build":"node build.js","prepack":"npm run build"},"_npmUser":{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"},"overrides":{"react":"$react","react-dom":"$react-dom"},"_npmVersion":"11.14.1","description":"Discord HTML transcript generator with Components V2, threads, polls, voice playback, and search. Drop-in replacement for discord-html-transcripts.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"react":"^19.1.0","sharp":"^0.34.3","twemoji":"^14.0.2","react-dom":"^19.1.0","discord-markdown-parser":"^1.3.1","@derockdev/discord-components-core":"^3.6.1"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","discord.js":"^14.26.4"},"peerDependencies":{"discord.js":"^14.26.4 || ^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/better-discord-transcripts_1.0.4_1780857245693_0.20209403536040083","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"better-discord-transcripts","version":"1.0.5","keywords":["discord","discord.js","transcript","html-transcript","discord-transcripts","discord-html-transcripts","components-v2","ticket","modmail"],"license":"Apache-2.0","_id":"better-discord-transcripts@1.0.5","maintainers":[{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"}],"homepage":"https://www.npmjs.com/package/better-discord-transcripts","dist":{"shasum":"e37d62d8cba4b6fce3ec3a4bc0136c17e7ab60eb","tarball":"https://registry.npmjs.org/better-discord-transcripts/-/better-discord-transcripts-1.0.5.tgz","fileCount":46,"integrity":"sha512-iG5U1KMyH/6NRsJnmuer2j7gxYJOIHD/8GTMwUvXMQVY7/Be+K5nfWmqTNEsPyDRXICmZCoRThOkEXaPLI2nBQ==","signatures":[{"sig":"MEUCICZEZx6NZlxk38AGrF/zMHXEYF0qVZbEMq2aZQi3nVckAiEAvVwoGtCbo0vJHmOzAV62oMhjMTLs7u0WRRNw/WI9OGY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":214603},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js","require":"./dist/index.js"}},"scripts":{"build":"node build.js","prepack":"npm run build"},"_npmUser":{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"},"overrides":{"react":"$react","react-dom":"$react-dom"},"_npmVersion":"11.14.1","description":"Discord HTML transcript generator with Components V2, threads, polls, voice playback, and search. Drop-in replacement for discord-html-transcripts.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"react":"^19.1.0","sharp":"^0.34.3","twemoji":"^14.0.2","react-dom":"^19.1.0","discord-markdown-parser":"^1.3.1","@derockdev/discord-components-core":"^3.6.1"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","discord.js":"^14.26.4"},"peerDependencies":{"discord.js":"^14.26.4 || ^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/better-discord-transcripts_1.0.5_1780857527593_0.2823900164394937","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"better-discord-transcripts","version":"1.0.6","keywords":["discord","discord.js","transcript","html-transcript","discord-transcripts","discord-html-transcripts","components-v2","ticket","modmail"],"license":"Apache-2.0","_id":"better-discord-transcripts@1.0.6","maintainers":[{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"}],"homepage":"https://www.npmjs.com/package/better-discord-transcripts","dist":{"shasum":"d4c7da846c99eb58797e0712a3ed3f8f28a4a9a2","tarball":"https://registry.npmjs.org/better-discord-transcripts/-/better-discord-transcripts-1.0.6.tgz","fileCount":46,"integrity":"sha512-sznbtggnU8IDMQV5C7fJuCNfNDdKuVX5dIadHte0MvSD4VYecxWExHCdKpZzUsV9hYmZy0O27gFA9FFVI6NkVw==","signatures":[{"sig":"MEUCIQDOm/KnbvIsogZjbpFtT+Zyi4BBM6HyNqGOSDhrcMeCeQIgECoRbg3SIdvqTdsr5JuH8sEc7qnzQVjvhry/ZWj61hw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":216455},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js","require":"./dist/index.js"}},"scripts":{"build":"node build.js","prepack":"npm run build"},"_npmUser":{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"},"overrides":{"react":"$react","react-dom":"$react-dom"},"_npmVersion":"11.14.1","description":"Discord HTML transcript generator with Components V2, threads, polls, voice playback, and search. Drop-in replacement for discord-html-transcripts.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"react":"^19.1.0","sharp":"^0.34.3","twemoji":"^14.0.2","react-dom":"^19.1.0","discord-markdown-parser":"^1.3.1","@derockdev/discord-components-core":"^3.6.1"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","discord.js":"^14.26.4"},"peerDependencies":{"discord.js":"^14.26.4 || ^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/better-discord-transcripts_1.0.6_1780932808080_0.6667655568557225","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"better-discord-transcripts","version":"1.0.7","keywords":["discord","discord.js","transcript","html-transcript","discord-transcripts","discord-html-transcripts","components-v2","ticket","modmail"],"license":"Apache-2.0","_id":"better-discord-transcripts@1.0.7","maintainers":[{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"}],"homepage":"https://www.npmjs.com/package/better-discord-transcripts","dist":{"shasum":"f7115411e7783afdf714b8965d5a64a57143475f","tarball":"https://registry.npmjs.org/better-discord-transcripts/-/better-discord-transcripts-1.0.7.tgz","fileCount":46,"integrity":"sha512-K3x6gZXGv5Wl1ZXAzzh6JFa0GrJ1ywHosFqXT0V9qsuBv7/MYMYoY+H7rEpF79jRa+L7aUpP50Bwyghdlj5xng==","signatures":[{"sig":"MEUCIQDCm5zeJQa9dGPpK5cR4dWl2zKl8+pasUotwPSyrKLxxwIgfKTFc8FSWHM5EMPJRjDW+TSDCAQSEFTmHfwZ6c1oajE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":216455},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js","require":"./dist/index.js"}},"scripts":{"build":"node build.js","prepack":"npm run build"},"_npmUser":{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"},"overrides":{"react":"$react","react-dom":"$react-dom"},"_npmVersion":"11.14.1","description":"Discord HTML transcript generator with Components V2, threads, polls, voice playback, and search. Drop-in replacement for discord-html-transcripts.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"react":"^19.1.0","sharp":"^0.34.3","twemoji":"^14.0.2","react-dom":"^19.1.0","discord-markdown-parser":"^1.3.1","@derockdev/discord-components-core":"^3.6.1"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","discord.js":"^14.26.4"},"peerDependencies":{"discord.js":"^14.26.4 || ^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/better-discord-transcripts_1.0.7_1780936410714_0.08215718417421636","host":"s3://npm-registry-packages-npm-production"}},"1.0.8":{"name":"better-discord-transcripts","version":"1.0.8","keywords":["discord","discord.js","transcript","html-transcript","discord-transcripts","discord-html-transcripts","components-v2","ticket","modmail"],"license":"Apache-2.0","_id":"better-discord-transcripts@1.0.8","maintainers":[{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"}],"homepage":"https://www.npmjs.com/package/better-discord-transcripts","dist":{"shasum":"8d84404837fe4ccf8bb9040ed68938499c150662","tarball":"https://registry.npmjs.org/better-discord-transcripts/-/better-discord-transcripts-1.0.8.tgz","fileCount":46,"integrity":"sha512-Pz2LpLJxCpd4QaUi0ybWigusLsRd5qQUgAMbWZUaiW7KhTDDXtmFJ5vGy7/bYgEjnWvXjepIY1i+UfHAW3K6Jw==","signatures":[{"sig":"MEUCIAbG5Ca55ctw0oyFKPqEmvlGtL64o40VZZnGqaOKoTSlAiEA29MAO6lzRmh0V9nJUf9mUJ9vFLz8bkfKk+FigjEh91Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":217595},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js","require":"./dist/index.js"}},"scripts":{"build":"node build.js","prepack":"npm run build"},"_npmUser":{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"},"overrides":{"react":"$react","react-dom":"$react-dom"},"_npmVersion":"11.14.1","description":"Discord HTML transcript generator with Components V2, threads, polls, voice playback, and search. Drop-in replacement for discord-html-transcripts.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"react":"^19.1.0","sharp":"^0.34.3","twemoji":"^14.0.2","react-dom":"^19.1.0","discord-markdown-parser":"^1.3.1","@derockdev/discord-components-core":"^3.6.1"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","discord.js":"^14.26.4"},"peerDependencies":{"discord.js":"^14.26.4 || ^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/better-discord-transcripts_1.0.8_1780940011490_0.1876389044966802","host":"s3://npm-registry-packages-npm-production"}},"1.0.9":{"name":"better-discord-transcripts","version":"1.0.9","keywords":["discord","discord.js","transcript","html-transcript","discord-transcripts","discord-html-transcripts","components-v2","ticket","modmail"],"license":"Apache-2.0","_id":"better-discord-transcripts@1.0.9","maintainers":[{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"}],"homepage":"https://www.npmjs.com/package/better-discord-transcripts","dist":{"shasum":"10a9a41154fb9cfeb6da9d900bccfdd7118e3a0e","tarball":"https://registry.npmjs.org/better-discord-transcripts/-/better-discord-transcripts-1.0.9.tgz","fileCount":46,"integrity":"sha512-byA1JsznDTd/mDic1m2Jyqd0zJ14q8XFMx/wxZCQbUr6+MI7Fh8a6/ysyWLWQdumE2prx+qJRCK2CuqS0hUlvQ==","signatures":[{"sig":"MEQCICvxG76lfAqhqX1nIv/TbiCQDtJNg/yRMdW7CIfVSXAEAiAZ81By8DXDtYTnVJt07JB0q3Gg/DX7XAz971RGVDbCAg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":218725},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js","require":"./dist/index.js"}},"scripts":{"build":"node build.js","prepack":"npm run build"},"_npmUser":{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"},"overrides":{"react":"$react","react-dom":"$react-dom"},"_npmVersion":"11.14.1","description":"Discord HTML transcript generator with Components V2, threads, polls, voice playback, and search. Drop-in replacement for discord-html-transcripts.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"react":"^19.1.0","twemoji":"^14.0.2","react-dom":"^19.1.0","discord-markdown-parser":"^1.3.1","@derockdev/discord-components-core":"^3.6.1"},"_hasShrinkwrap":false,"devDependencies":{"sharp":"^0.34.3","esbuild":"^0.25.0","discord.js":"^14.26.4"},"peerDependencies":{"sharp":"^0.34.3","discord.js":"^14.26.4 || ^15.0.0"},"peerDependenciesMeta":{"sharp":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/better-discord-transcripts_1.0.9_1780950590101_0.966944669615746","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"better-discord-transcripts","version":"2.0.0","description":"Discord HTML transcript generator with Components V2, threads, polls, voice playback, and search. Drop-in replacement for discord-html-transcripts.","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","require":"./dist/index.js","default":"./dist/index.js"}},"type":"commonjs","scripts":{"build":"node build.js","prepack":"npm run build"},"keywords":["discord","discord.js","transcript","html-transcript","discord-transcripts","discord-html-transcripts","components-v2","ticket","modmail"],"license":"Apache-2.0","homepage":"https://www.npmjs.com/package/better-discord-transcripts","dependencies":{"@derockdev/discord-components-core":"^3.6.1","discord-markdown-parser":"^1.3.1","react":"^19.1.0","react-dom":"^19.1.0","twemoji":"^14.0.2"},"peerDependencies":{"discord.js":"^14.26.4 || ^15.0.0","sharp":"^0.34.3"},"peerDependenciesMeta":{"sharp":{"optional":true}},"devDependencies":{"discord.js":"^14.26.4","esbuild":"^0.25.0","sharp":"^0.34.3"},"overrides":{"react":"$react","react-dom":"$react-dom"},"engines":{"node":">=18"},"_id":"better-discord-transcripts@2.0.0","_nodeVersion":"26.1.0","_npmVersion":"11.14.1","dist":{"integrity":"sha512-yBcd/kFPzvUUpZ1NePbkI5DlJtppcTho8BOfP0s8caDKds8aOgf/jb7zVueMkl+GuFb4CzXUCqRfoup4+h/xoQ==","shasum":"0b163d883bf4de8465e234bfdf27e0347205a1d5","tarball":"https://registry.npmjs.org/better-discord-transcripts/-/better-discord-transcripts-2.0.0.tgz","fileCount":46,"unpackedSize":220574,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEBL4XHSLlvn31KVDKMFcs2mkrMuFv2RVeH7ZJvA7CrqAiEA+DAX3HXhFw13ieIgR5U+kQ8VpdICbHdC6O1Pz3VAt24="}]},"_npmUser":{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"},"directories":{},"maintainers":[{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/better-discord-transcripts_2.0.0_1780950984352_0.39176975006792847"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-07T15:40:26.635Z","modified":"2026-06-08T20:36:24.636Z","1.1.0":"2026-06-07T15:40:26.865Z","1.1.1":"2026-06-07T15:42:32.518Z","1.1.2":"2026-06-07T15:56:14.847Z","1.1.5":"2026-06-07T16:19:53.245Z","1.1.7":"2026-06-07T16:27:45.106Z","1.0.0":"2026-06-07T16:29:57.062Z","1.0.1":"2026-06-07T17:04:15.764Z","1.0.2":"2026-06-07T17:35:07.180Z","1.0.3":"2026-06-07T18:00:24.735Z","9.9.9":"2026-06-07T18:20:39.682Z","1.0.4":"2026-06-07T18:34:05.844Z","1.0.5":"2026-06-07T18:38:47.734Z","1.0.6":"2026-06-08T15:33:28.207Z","1.0.7":"2026-06-08T16:33:30.881Z","1.0.8":"2026-06-08T17:33:31.670Z","1.0.9":"2026-06-08T20:29:50.281Z","2.0.0":"2026-06-08T20:36:24.516Z"},"license":"Apache-2.0","homepage":"https://www.npmjs.com/package/better-discord-transcripts","keywords":["discord","discord.js","transcript","html-transcript","discord-transcripts","discord-html-transcripts","components-v2","ticket","modmail"],"description":"Discord HTML transcript generator with Components V2, threads, polls, voice playback, and search. Drop-in replacement for discord-html-transcripts.","maintainers":[{"name":"keyswithy","email":"npmjs.eezmp@passmail.com"}],"readme":"# better-discord-transcripts\n\n[![npm version](https://img.shields.io/npm/v/better-discord-transcripts.svg)](https://www.npmjs.com/package/better-discord-transcripts)\n[![license](https://img.shields.io/npm/l/better-discord-transcripts.svg)](./LICENSE)\n[![node](https://img.shields.io/node/v/better-discord-transcripts.svg)](https://nodejs.org)\n\nA nicely formatted HTML transcript generator for [discord.js](https://discord.js.org/) v14/v15.\nDrop-in replacement for [discord-html-transcripts](https://www.npmjs.com/package/discord-html-transcripts), with Components V2, thread modals, voice playback, and a built-in search UI. Inspired by community forks such as [discord.js-html-transcript](https://www.npmjs.com/package/discord.js-html-transcript).\n\nImages and voice messages are **inlined by default** so transcripts stay readable offline. With [sharp](https://sharp.pixelplumbing.com/) installed, images are compressed to WebP - much smaller HTML files.\n\n## Project status\n\nIn my opinion, the project is **feature-complete** for now. I will still **update it regularly** - bug fixes, discord.js changes, and small improvements as needed.\n\n## Requirements\n\n- **Node.js 18+**\n- **discord.js** `^14.26.4` or `^15` (peer dependency - install it yourself)\n- **[sharp](https://sharp.pixelplumbing.com/)** (optional peer dependency - recommended for `saveImages: true`)\n\nSharp is **not** bundled. Install it yourself if you want WebP resize/compression (strongly recommended for ticket bots - without sharp, inlined transcripts can get very large).\n\n## Install\n\n### Base install (no image compression)\n\n```bash\nnpm install better-discord-transcripts discord.js\n```\n\n`package.json`:\n\n```json\n{\n  \"dependencies\": {\n    \"better-discord-transcripts\": \"^2.0.0\",\n    \"discord.js\": \"^14.26.4\"\n  }\n}\n```\n\n### With sharp (highly recommended)\n\n```bash\nnpm install better-discord-transcripts discord.js sharp\n```\n\n`package.json`:\n\n```json\n{\n  \"dependencies\": {\n    \"better-discord-transcripts\": \"^2.0.0\",\n    \"discord.js\": \"^14.26.4\",\n    \"sharp\": \"^0.34.3\"\n  }\n}\n```\n\n## Migration from `discord-html-transcripts`\n\nOne line change. Same options, same return types:\n\n```diff\n- const { createTranscript } = require('discord-html-transcripts');\n+ const { createTranscript } = require('better-discord-transcripts');\n```\n\nYour existing ticket code still works.\n\n## Quick start\n\nCreate a full channel transcript in **3 lines of code**!:\n\n```js\nconst { createTranscript } = require('better-discord-transcripts');\n\nconst attachment = await createTranscript(channel, { limit: -1 });\nawait logChannel.send({ files: [attachment] });\n```\n\nIf you omit `limit` (or set `-1`), the full channel history is fetched, including thread messages on posts with `hasThread`.\n\n## Image compression (sharp)\n\nWith default options, attachments and embed images are downloaded and embedded as **WebP base64** instead of raw PNG/JPEG. That keeps transcript file size down while everything still opens from a single `.html` file with no external CDN links.\n\n| Setting | Value |\n| ------- | ----- |\n| Library | [sharp](https://sharp.pixelplumbing.com/) (optional peer - `npm install sharp`) |\n| Format | WebP |\n| Max dimension | 720px (longest side) |\n| Quality | ~70% |\n| Toggle | `saveImages: false` skips download and inlining entirely |\n| Sharp off | `useSharp: false` keeps inlining but skips resize/WebP (raw base64) |\n\n**Not recommended:** turning sharp off (`useSharp: false`) while keeping `saveImages: true`. Images stay full resolution and original format (often PNG/JPEG), so a single ticket transcript can easily reach tens or hundreds of MB. Use it only as a fallback when sharp cannot load on your platform.\n\nSharp is probed when your bot loads the package (`require('better-discord-transcripts')`). If it is not installed or fails to load, you get a one-time warning at startup (with install instructions). During transcript generation the library falls back to the original image format and still produces HTML - but files may be much larger.\n\n```js\n// Default - images compressed with sharp\nawait createTranscript(channel);\n\n// Skip images - smallest output, but Discord CDN links may expire later\nawait createTranscript(channel, { saveImages: false });\n\n// Fallback only - not recommended for production (transcripts can get very large)\nawait createTranscript(channel, { useSharp: false });\n```\n\n## Options\n\nSame options as `discord-html-transcripts`, plus `saveVoiceMessages`:\n\n| Option | Type | Default | Description |\n| ------ | ---- | ------- | ----------- |\n| `limit` | `number` | all messages | Max messages to fetch. `-1` or omit = everything |\n| `filter` | `(m) => boolean` | none | Filter messages before render |\n| `returnType` | `'attachment'`, `'buffer'`, `'string'` | `'attachment'` | Or use the `ExportReturnType` enum |\n| `filename` | `string` | `transcript-{channelName}.html` | Attachment filename |\n| `saveImages` | `boolean` | `true` | Download images and inline as WebP base64 via sharp (max 720px, ~70% quality) |\n| `useSharp` | `boolean` | `true` | Resize/compress inlined images with sharp; `false` = raw base64 (not recommended - huge HTML files) |\n| `saveVoiceMessages` | `boolean` | `true` | Download voice messages and inline as base64 so they stay playable after Discord URLs expire |\n| `footerText` | `string` | `Exported {number} message{s}.` | Footer line before the powered-by credit |\n| `poweredBy` | `boolean` | `true` | Show \"Powered by better-discord-transcripts\" |\n| `favicon` | `'guild'` or `string` | `'guild'` | Guild icon or a custom URL |\n| `hydrate` | `boolean` | `false` | Server-side hydration of web components (slower, works offline) |\n| `callbacks` | object | auto | `resolveUser`, `resolveRole`, `resolveChannel`, `resolveImageSrc`, `resolveVoiceSrc` |\n\n### Disable image or voice inlining\n\n```js\n// No images (voice messages still inlined by default)\nawait createTranscript(channel, { saveImages: false });\n\n// Voice only (images stay as Discord CDN links, but links may break later - remember that!)\nawait createTranscript(channel, { saveImages: false, saveVoiceMessages: true });\n\n// Neither - smallest file, but CDN links may break later - remember that!\nawait createTranscript(channel, { saveImages: false, saveVoiceMessages: false });\n```\n\n### TypeScript\n\n```ts\nimport { createTranscript, ExportReturnType } from 'better-discord-transcripts';\n\nconst transcript = await createTranscript(channel, {\n  returnType: ExportReturnType.String,\n});\n```\n\n### `generateFromMessages` - when you already have messages\n\n`createTranscript` fetches messages from Discord for you.\n\n`generateFromMessages` skips that step. You pass a `Message[]` or `Collection` you already loaded (custom fetch, cached ticket log, filtered list, etc.) and get the same HTML output.\n\nUse it when:\n\n- you fetched messages yourself (custom pagination, database, bot cache)\n- you want to render only a subset without calling the API again\n- you deleted the channel but still have message objects in memory\n\n```js\nconst { generateFromMessages } = require('better-discord-transcripts');\n\n// messages = Message[] or Collection from channel.messages.fetch(), your DB, etc.\nconst attachment = await generateFromMessages(messages, channel, {\n  poweredBy: false,\n  filename: 'ticket-log.html',\n});\n```\n\nSame options as `createTranscript`, except there is no `limit` or `filter` (you control the array yourself). `saveImages`, `useSharp`, and `saveVoiceMessages` default to `true` here as well.\n\n## Interactive HTML viewer\n\nBuilt into every transcript:\n\n- **Search** - find messages by text or ID, keyboard navigation\n- **Pinned messages** - header panel with jump-to-message\n- **Member list** - participants and message counts\n- **Thread modal** - click a thread bar to read the full thread inline\n- **Image lightbox** - click images to zoom\n- **Voice playback** - play button and waveform (works offline when `saveVoiceMessages` is on)\n- **Spoiler reveal** - click to reveal spoilers\n\n## Content rendered\n\n- Plain text, markdown, mentions, emojis, timestamps\n- Embeds, attachments, stickers, reactions\n- Replies, forwards, slash command headers\n- **Components V2** - Container, Section, TextDisplay, Media Gallery, Thumbnail, File, Separator, buttons\n- Polls with vote bars\n- **Voice messages** - waveform from `attachment.waveform`, duration, inline `<audio>`\n- System messages - pins, thread created, joins, and more\n- Server tags, role icons, verified bot badges\n- Cross-server reply indicators\n\n## Included by default\n\n- Full channel fetch when `limit` is omitted\n- Full thread fetch on messages with `hasThread`\n- Image inlining when `saveImages: true` (WebP via sharp when installed)\n- Images inlined as WebP base64 with sharp (720px max, ~70% quality)\n- Voice messages inlined as base64 (`saveVoiceMessages: true`) for offline playback\n\n## API\n\n| Export | Description |\n| ------ | ----------- |\n| `createTranscript(channel, options?)` | Fetch messages from a channel and render HTML |\n| `generateFromMessages(messages, channel, options?)` | Render HTML from messages you already have |\n| `ExportReturnType` | `Attachment`, `Buffer`, or `String` |\n| `default` | `{ createTranscript, generateFromMessages }` |\n\n## Changelog\n\n<details open>\n<summary><strong>2.0.0</strong> (latest)</summary>\n\n- Project marked as feature-complete; regular maintenance updates continue\n- Collapsible changelog section in README\n- Sharp probed at bot startup when the package is loaded\n\n</details>\n\n<details>\n<summary><strong>1.0.9</strong></summary>\n\n- `sharp` moved to optional peer dependency (smaller install without image compression)\n- `useSharp` option to skip WebP resize/compression\n- `isSharpAvailable()` export and automatic fallback when sharp is missing\n- README install examples with and without sharp\n\n</details>\n\n<details>\n<summary><strong>1.0.8</strong></summary>\n\n- Slightly darker embed and container backgrounds\n- Footer pill: `Exported X messages | Powered by better-discord-transcripts`\n- Unicode separators in UI changed to `-` where applicable\n\n</details>\n\n<details>\n<summary><strong>1.0.7</strong></summary>\n\n- Lighter inline and block code background (`#2b2d31`) closer to Discord\n\n</details>\n\n<details>\n<summary><strong>1.0.6</strong></summary>\n\n- Inline `` `code` `` styling like Discord (inherit font size, wrap-friendly background)\n- Fenced code blocks (```) match inline code style\n\n</details>\n\n<details>\n<summary><strong>1.0.5</strong></summary>\n\n- Removed dead emoji registry code\n- CDN derock version fix (strip `^` from component version)\n- Select menu options render as `<img>` instead of raw URLs\n\n</details>\n\n<details>\n<summary><strong>1.0.4</strong></summary>\n\n- `hydrate: true` by default for embed titles with custom emoji\n- Non-clickable emoji in messages, embeds, buttons, reactions, and polls\n- Embed title rendering fixes after hydration\n\n</details>\n\n## License\n\n[Apache-2.0](./LICENSE)\n\nFork and successor of [discord-html-transcripts](https://github.com/ItzDerock/discord-html-transcripts) by ItzDerock.\n","readmeFilename":"README.md"}