Skip to content

Commit e8fa093

Browse files
committed
enforce markdown image width to be <=100
add code block and copy button
1 parent 8d5ac25 commit e8fa093

2 files changed

Lines changed: 156 additions & 0 deletions

File tree

‎website/src/pages/parts/[slug].astro‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,75 @@ const { model, descriptionHtml } = Astro.props;
112112
<article set:html={descriptionHtml} />
113113
</section>
114114
</div>
115+
116+
117+
<script>
118+
// Wait for the DOM to fully load
119+
document.addEventListener("DOMContentLoaded", () => {
120+
// Find all code blocks inside the description section
121+
const preElements = document.querySelectorAll('.description pre');
122+
123+
preElements.forEach((pre) => {
124+
const codeElem = pre.querySelector('code');
125+
if (!codeElem) return;
126+
127+
// Extract the language name from the class (e.g., "language-python")
128+
let lang = 'TEXT';
129+
codeElem.classList.forEach(cls => {
130+
if (cls.startsWith('language-')) {
131+
lang = cls.replace('language-', '');
132+
}
133+
});
134+
135+
// Create the outer wrapper
136+
const wrapper = document.createElement('div');
137+
wrapper.className = 'code-wrapper';
138+
139+
// Insert wrapper just before the pre element, then move the pre inside it
140+
pre.parentNode.insertBefore(wrapper, pre);
141+
142+
// Create the header bar
143+
const header = document.createElement('div');
144+
header.className = 'code-header';
145+
146+
// Add the language label
147+
const langSpan = document.createElement('span');
148+
langSpan.className = 'code-lang';
149+
langSpan.innerText = lang;
150+
151+
// Add the copy button
152+
const copyBtn = document.createElement('button');
153+
copyBtn.className = 'copy-btn';
154+
copyBtn.innerText = 'Copy';
155+
156+
// Attach copy functionality
157+
copyBtn.addEventListener('click', async () => {
158+
try {
159+
// Write the text content of the code block to the clipboard
160+
await navigator.clipboard.writeText(codeElem.innerText);
161+
162+
// Visual feedback
163+
copyBtn.innerText = 'Copied!';
164+
copyBtn.classList.add('copied');
165+
166+
// Reset button after 2 seconds
167+
setTimeout(() => {
168+
copyBtn.innerText = 'Copy';
169+
copyBtn.classList.remove('copied');
170+
}, 2000);
171+
} catch (err) {
172+
console.error('Failed to copy text: ', err);
173+
}
174+
});
175+
176+
// Assemble the DOM structure
177+
header.appendChild(langSpan);
178+
header.appendChild(copyBtn);
179+
180+
wrapper.appendChild(header);
181+
wrapper.appendChild(pre);
182+
});
183+
});
184+
</script>
115185
</body>
116186
</html>

‎website/src/styles/global.css‎

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,89 @@ body {
172172
align-items: center;
173173
margin-bottom: 2rem;
174174
}
175+
176+
/* --- Markdown Description Content --- */
177+
.description img {
178+
max-width: 100%;
179+
height: auto;
180+
border-radius: 6px; /* Matches the rounded corners of your UI */
181+
display: block;
182+
margin: 1rem auto; /* Centers the image if it is smaller than the container */
183+
box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* Optional: adds a subtle depth */
184+
}
185+
186+
/* --- Code Blocks --- */
187+
.code-wrapper {
188+
margin: 1.5rem 0;
189+
border-radius: 8px;
190+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
191+
overflow: hidden;
192+
background: #1e1e1e; /* Dark theme for the header */
193+
}
194+
195+
.code-header {
196+
display: flex;
197+
justify-content: space-between;
198+
align-items: center;
199+
padding: 0.5rem 1rem;
200+
background: #252526;
201+
border-bottom: 1px solid #333;
202+
}
203+
204+
.code-lang {
205+
color: #9cdcfe;
206+
font-size: 0.75rem;
207+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
208+
font-weight: 600;
209+
text-transform: uppercase;
210+
letter-spacing: 0.5px;
211+
}
212+
213+
.copy-btn {
214+
background: transparent;
215+
color: #a9a9a9;
216+
border: 1px solid #555;
217+
padding: 0.25rem 0.75rem;
218+
border-radius: 4px;
219+
font-size: 0.75rem;
220+
cursor: pointer;
221+
transition: all 0.2s ease;
222+
}
223+
224+
.copy-btn:hover {
225+
background: #333;
226+
color: #fff;
227+
border-color: #888;
228+
}
229+
230+
.copy-btn.copied {
231+
background: #2ea043;
232+
color: #fff;
233+
border-color: #2ea043;
234+
}
235+
236+
.description pre {
237+
background: #1e1e1e !important;
238+
color: #d4d4d4;
239+
padding: 1rem;
240+
overflow-x: auto;
241+
margin: 0;
242+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
243+
font-size: 0.9rem;
244+
line-height: 1.5;
245+
}
246+
247+
.description pre code {
248+
background: transparent;
249+
padding: 0;
250+
}
251+
252+
/* Inline code styles (not blocks) */
253+
.description :not(pre) > code {
254+
background: #eaeaea;
255+
color: #d73a49;
256+
padding: 0.2em 0.4em;
257+
border-radius: 4px;
258+
font-size: 0.85em;
259+
font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
260+
}

0 commit comments

Comments
 (0)