Skip to content

Commit 1882295

Browse files
committed
feat: Add markdown processing utility with custom rendering and global styling.
1 parent 9f33936 commit 1882295

2 files changed

Lines changed: 67 additions & 4 deletions

File tree

‎app/globals.css‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,45 @@
260260
margin-bottom: 1em !important;
261261
}
262262

263+
/* Code Block with Copy Button Wrapper */
264+
.markdown-body [data-copy-wrapper] {
265+
position: relative;
266+
margin: 1rem 0;
267+
}
268+
269+
.markdown-body [data-copy-wrapper] pre {
270+
margin: 0 !important;
271+
}
272+
273+
/* Copy Button */
274+
.markdown-body .copy-btn {
275+
position: absolute;
276+
top: 0.5rem;
277+
right: 0.5rem;
278+
z-index: 10;
279+
display: flex;
280+
align-items: center;
281+
justify-content: center;
282+
width: 2rem;
283+
height: 2rem;
284+
padding: 0;
285+
border: 1px solid rgba(255, 255, 255, 0.2);
286+
border-radius: 0.375rem;
287+
background-color: #121212;
288+
color: white;
289+
cursor: pointer;
290+
transition: background-color 0.2s ease;
291+
}
292+
293+
.markdown-body .copy-btn:hover {
294+
background-color: #202020;
295+
}
296+
297+
.markdown-body .copy-btn svg {
298+
width: 16px;
299+
height: 16px;
300+
}
301+
263302
.markdown-body pre code {
264303
background-color: transparent !important;
265304
padding: 0 !important;

‎lib/markdown.ts‎

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ export async function processMarkdown(content: string): Promise<string> {
5959
const safeCode = text.replace(/"/g, "&quot;");
6060

6161
return `
62-
<div class="relative group my-4" data-copy-wrapper="true">
62+
<div data-copy-wrapper="true">
6363
<button
6464
type="button"
65-
class="copy-btn absolute top-2 right-2 z-10 h-8 w-8 flex items-center justify-center rounded-md border border-white/20 bg-[#121212] text-white hover:bg-[#202020] transition-all"
65+
class="copy-btn"
6666
aria-label="Copy code to clipboard"
6767
title="Copy"
6868
data-code="${safeCode}"
@@ -85,10 +85,17 @@ export async function processMarkdown(content: string): Promise<string> {
8585

8686
const cleanContent = sanitizeHtml(String(rawContent), {
8787
allowedTags: sanitizeHtml.defaults.allowedTags.concat([
88+
"img",
8889
"iframe",
8990
"button",
9091
"svg",
9192
"path",
93+
"rect",
94+
"line",
95+
"circle",
96+
"polyline",
97+
"polygon",
98+
"div",
9299
]),
93100
allowedAttributes: {
94101
a: ["href", "name", "target", "rel", "title"],
@@ -104,9 +111,26 @@ export async function processMarkdown(content: string): Promise<string> {
104111
"title",
105112
],
106113
button: ["id", "class", "data-code", "aria-label", "title", "type"],
114+
div: ["class", "data-copy-wrapper"],
107115
"*": ["id", "class"],
108-
svg: ["xmlns", "width", "height", "viewBox", "fill"],
109-
path: ["d"],
116+
svg: [
117+
"xmlns",
118+
"width",
119+
"height",
120+
"viewBox",
121+
"fill",
122+
"stroke",
123+
"stroke-width",
124+
"stroke-linecap",
125+
"stroke-linejoin",
126+
"aria-hidden",
127+
],
128+
path: ["d", "fill", "stroke"],
129+
rect: ["x", "y", "width", "height", "rx", "ry", "fill", "stroke"],
130+
line: ["x1", "y1", "x2", "y2", "stroke"],
131+
circle: ["cx", "cy", "r", "fill", "stroke"],
132+
polyline: ["points", "fill", "stroke"],
133+
polygon: ["points", "fill", "stroke"],
110134
},
111135
allowedSchemes: ["http", "https", "mailto", "tel"],
112136
allowedSchemesByTag: {

0 commit comments

Comments
 (0)