import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" import style from "./styles/buttons8831.scss" import rawButtonsData from "./buttons.json" import DOMPurify from "dompurify" interface ButtonData { url?: string image?: string alt?: string title?: string type?: string contentType?: "image" | "iframe" | "text" | "custom" iframeAttributes?: { [key: string]: string } border?: [string, string] // Array of two colors for the border text?: string // For "text" contentType customContent?: string // For "custom" contentType textColor?: string // For specifying text color in "text" contentType } export default (() => { const Btn8831: QuartzComponent = (props: QuartzComponentProps) => { const { displayClass } = props const buttonsData = rawButtonsData as ButtonData[] // Group buttons by type const groupedButtons = groupButtonsByType(buttonsData) // Define the order of types const typeOrder = ["friend", "standard", "misc"] return (
{typeOrder.map((type, index) => { const buttons = groupedButtons[type] if (buttons && buttons.length > 0) { return (
{/* Render buttons of the current type */}
{buttons.map((button, idx) => (
{renderButtonContent(button)}
))}
{/* Add a horizontal line after the group except for the last one */} {index < typeOrder.length - 1 &&
}
) } return null })}
) } Btn8831.css = style return Btn8831 }) satisfies QuartzComponentConstructor function groupButtonsByType(buttons: ButtonData[]) { const groups: { [key: string]: ButtonData[] } = { misc: [], friend: [], standard: [], } buttons.forEach((button) => { let type = button.type?.toLowerCase() || "standard" if (type === "fren") type = "friend" if (!groups[type]) type = "standard" // Default to 'standard' if type is unrecognized groups[type].push(button) }) return groups } function renderButtonContent(button: ButtonData): preact.VNode | null { const contentType = button.contentType?.toLowerCase() || "image" let content: preact.VNode | null = null if (contentType === "image") { // ... existing code for image ... } else if (contentType === "iframe") { // ... existing code for iframe ... } else if (contentType === "text") { const borderColors = button.border || ["#000", "#000"] const textContent = button.text || "" const textColor = button.textColor || "#000" // **Important:** Sanitize the text content to prevent XSS attacks. // Install DOMPurify: npm install dompurify const sanitizedTextContent = DOMPurify.sanitize(textContent) const divStyle = { width: "88px", height: "31px", boxSizing: "border-box", borderStyle: "solid", borderWidth: "2px", borderTopColor: borderColors[0], borderRightColor: borderColors[0], borderBottomColor: borderColors[1], borderLeftColor: borderColors[1], display: "flex", alignItems: "center", justifyContent: "center", fontSize: "12px", overflow: "hidden", color: textColor, } const textElement = (
) if (button.url) { content = {textElement} } else { content = textElement } } else if (contentType === "custom") { // ... existing code for custom ... } else { return null } return content }