enerthya.dev-message-renderer
v1.0.0
Published
Discord message and embed renderer to safe HTML. Inspired by Loritta's loritta-dashboard:message-renderer module.
Downloads
7
Maintainers
Readme
enerthya.dev-message-renderer
Renders Discord messages and embeds to safe HTML. Inspired by Loritta's
loritta-dashboard:message-renderermodule. Part of the Enerthya package ecosystem.
Features
- Zero Discord.js dependency — works in Node.js (backend) and browser (React)
- XSS-safe — all raw text is HTML-escaped before processing
- Discord markdown: bold, italic, underline, strikethrough, spoiler, inline code, code blocks, block quotes, headers (H1–H3)
- Mentions:
<@USER>,<#CHANNEL>,<@&ROLE>,@everyone,@here - Embed renderer: author, title, description, fields (inline), thumbnail, image, footer, timestamp, color pill
- Full message preview: content + embed combined
- Ready-made CSS via
getRendererCSS()— dark Discord aesthetic - Supports both Guild schema format and
EmbedBuilder.toJSON()format
Installation
npm install enerthya.dev-message-rendererQuick Start
const {
renderDiscordMarkdown,
renderEmbed,
renderMessage,
getRendererCSS,
} = require("enerthya.dev-message-renderer");
// Markdown
renderDiscordMarkdown("**Hello** _world_!");
// → "<strong>Hello</strong> <em>world</em>!"
// Embed (Guild schema format)
renderEmbed({
title: "Bem-vindo!",
description: "Olá **{member:name}**",
color: "#57F287",
thumbnail: true, // boolean = show member avatar placeholder
footer: "Enerthya Bot",
});
// Full message
renderMessage({
content: "Olá @everyone!",
embed: { title: "Server Update", color: "#5865F2" },
});
// CSS injection (React)
<style>{getRendererCSS()}</style>API Reference
Markdown
renderDiscordMarkdown(text) → string
Converts a Discord message string to safe HTML.
renderDiscordMarkdown("**bold** _italic_ ~~strike~~ `code`");
renderDiscordMarkdown("# Header\n> Quote\n```js\nconst x = 1;\n```");
renderDiscordMarkdown("<@123456789> check <#987654321>");Supported syntax:
| Discord | HTML |
|---------|------|
| **bold** | <strong> |
| *italic* or _italic_ | <em> |
| __underline__ | <u> |
| ~~strikethrough~~ | <s> |
| ||spoiler|| | <span class="discord-spoiler"> |
| `code` | <code class="discord-inline-code"> |
| ```lang\n...\n``` | <pre class="discord-code-block"> |
| # H1, ## H2, ### H3 | <h1>, <h2>, <h3> |
| > quote | <blockquote class="discord-quote"> |
| <@USER_ID> | <span class="discord-mention--user"> |
| <#CHANNEL_ID> | <span class="discord-mention--channel"> |
| <@&ROLE_ID> | <span class="discord-mention--role"> |
| @everyone, @here | <span class="discord-mention--broadcast"> |
Embed
renderEmbed(embed, options?) → string
Renders a Discord embed object to HTML.
Accepts two input formats:
Guild schema format (from welcome/farewell config):
renderEmbed({
title: "Welcome!",
description: "Hello **{member:name}**",
color: "#5865F2",
thumbnail: true, // boolean: show member avatar placeholder
author: true, // boolean: show member as author
footer: "My Server",
image: "https://example.com/banner.png",
disabled: false,
});EmbedBuilder.toJSON() format (from SavedEmbeds):
renderEmbed({
title: "Hello",
description: "Description here",
color: 0x5865F2,
url: "https://enerthya.dev",
author: { name: "Author", icon_url: "https://..." },
thumbnail: { url: "https://..." },
image: { url: "https://..." },
footer: { text: "Footer", icon_url: "https://..." },
timestamp: new Date(),
fields: [
{ name: "Field 1", value: "Value 1", inline: true },
{ name: "Field 2", value: "Value 2", inline: true },
],
});Options:
options.avatarUrl— Member avatar URL for booleanthumbnail: true/author: truemodes.
renderMessage(message, options?) → string
Renders a full Discord message: optional content + optional embed.
renderMessage({
content: "Olá @everyone!", // optional
embed: { title: "Update" }, // optional — embed.disabled = true hides the embed
}, { avatarUrl: "https://..." });CSS
getRendererCSS() → string
Returns a ready-made CSS string for all discord-* class names.
// React
import { getRendererCSS } from "enerthya.dev-message-renderer";
function MessagePreview({ content, embed }) {
return (
<>
<style>{getRendererCSS()}</style>
<div dangerouslySetInnerHTML={{ __html: renderMessage({ content, embed }) }} />
</>
);
}// Plain HTML
const { getRendererCSS } = require("enerthya.dev-message-renderer");
document.head.insertAdjacentHTML("beforeend", `<style>${getRendererCSS()}</style>`);Utilities
| Export | Description |
|--------|-------------|
| escapeHtml(text) | HTML-escapes raw text (XSS protection) |
| normalizeColor(color) | Normalizes hex/integer color to #RRGGBB |
| DEFAULT_EMBED_COLOR | "#5865F2" (Discord blurple) |
| LIMITS | Discord character limits (EMBED_TITLE, EMBED_DESCRIPTION, etc.) |
CSS Classes Reference
| Class | Element |
|-------|---------|
| .discord-message | Message container |
| .discord-message-content | Text content above embed |
| .discord-embed | Embed wrapper (has --embed-color CSS variable) |
| .discord-embed-title | Embed title |
| .discord-embed-description | Embed description |
| .discord-embed-author | Author row |
| .discord-embed-fields | Fields grid container |
| .discord-embed-field | Single field |
| .discord-embed-field--inline | Inline field |
| .discord-embed-thumbnail | Thumbnail image |
| .discord-embed-image | Large image |
| .discord-embed-footer | Footer row |
| .discord-mention--user | User mention |
| .discord-mention--channel | Channel mention |
| .discord-mention--role | Role mention |
| .discord-mention--broadcast | @everyone / @here |
| .discord-quote | Block quote |
| .discord-inline-code | Inline code |
| .discord-code-block | Code block |
| .discord-spoiler | Spoiler text |
| .discord-h1, .discord-h2, .discord-h3 | Headers |
License
MIT — Enerthya
