@@ -90,6 +90,7 @@ const WriteupDetail = () => {
9090 const tableOfContents = extractTableOfContents ( writeup ?. content || '' ) ;
9191 const categoryStyle = getCategoryStyle ( writeup ?. frontmatter . category || '' ) ;
9292
93+ // Improved markdown renderer: supports inline code and links on the same line
9394 const renderMarkdown = ( content : string ) => {
9495 let inCodeBlock = false ;
9596 let codeBlockContent = '' ;
@@ -179,16 +180,45 @@ const WriteupDetail = () => {
179180 return < li key = { index } className = "text-gray-300 ml-4 mb-2" > { line } </ li > ;
180181 }
181182
182- // Inline code
183- if ( line . includes ( '`' ) ) {
184- const parts = line . split ( '`' ) ;
183+ // Inline code and links together
184+ if ( line . includes ( '`' ) || / \[ ( [ ^ \] ] + ) \] \( ( [ ^ ) ] + ) \) / . test ( line ) ) {
185+ const elements = [ ] ;
186+ let idx = 0 ;
187+ const regex = / ( ` [ ^ ` ] + ` ) | ( \[ ( [ ^ \] ] + ) \] \( ( [ ^ ) ] + ) \) ) / g;
188+ let match ;
189+ while ( ( match = regex . exec ( line ) ) !== null ) {
190+ if ( match . index > idx ) {
191+ elements . push ( line . slice ( idx , match . index ) ) ;
192+ }
193+ if ( match [ 1 ] ) {
194+ // Inline code
195+ elements . push (
196+ < code key = { idx + '-code' } className = "bg-gray-800 px-1.5 py-0.5 rounded text-sm font-mono text-gray-200" >
197+ { match [ 1 ] . slice ( 1 , - 1 ) }
198+ </ code >
199+ ) ;
200+ } else if ( match [ 2 ] ) {
201+ // Markdown link
202+ elements . push (
203+ < a
204+ key = { idx + '-link' }
205+ href = { match [ 5 ] }
206+ target = "_blank"
207+ rel = "noopener noreferrer"
208+ className = "text-blue-400 underline break-all"
209+ >
210+ { match [ 4 ] }
211+ </ a >
212+ ) ;
213+ }
214+ idx = regex . lastIndex ;
215+ }
216+ if ( idx < line . length ) {
217+ elements . push ( line . slice ( idx ) ) ;
218+ }
185219 return (
186220 < p key = { index } className = "text-gray-300 leading-relaxed mb-4" >
187- { parts . map ( ( part , i ) =>
188- i % 2 === 0 ?
189- part :
190- < code key = { i } className = "bg-gray-800 px-1.5 py-0.5 rounded text-sm font-mono text-gray-200" > { part } </ code >
191- ) }
221+ { elements }
192222 </ p >
193223 ) ;
194224 }
@@ -276,26 +306,26 @@ const WriteupDetail = () => {
276306 < div className = "sticky top-24 bg-transparent border border-gray-700 rounded-lg p-6" >
277307 < h3 className = "font-semibold text-gray-100 mb-4" > Table of Contents</ h3 >
278308 < nav className = "space-y-2" >
279- { tableOfContents . map ( ( item ) => (
280- < a
281- key = { item . id }
282- href = { `#${ item . id } ` }
283- onClick = { e => {
284- e . preventDefault ( ) ;
285- const el = document . getElementById ( item . id ) ;
286- if ( el ) {
287- el . scrollIntoView ( { behavior : "smooth" , block : "start" } ) ;
288- }
289- } }
290- className = { `block text-sm hover:text-gray-100 transition-colors ${
291- item . level === 1 ? 'font-medium text-gray-100' :
292- item . level === 2 ? 'text-gray-300 pl-3' : 'text-gray-400 pl-6'
293- } `}
294- >
295- { item . text }
296- </ a >
297- ) ) }
298- </ nav >
309+ { tableOfContents . map ( ( item ) => (
310+ < a
311+ key = { item . id }
312+ href = { `#${ item . id } ` }
313+ onClick = { e => {
314+ e . preventDefault ( ) ;
315+ const el = document . getElementById ( item . id ) ;
316+ if ( el ) {
317+ el . scrollIntoView ( { behavior : "smooth" , block : "start" } ) ;
318+ }
319+ } }
320+ className = { `block text-sm hover:text-gray-100 transition-colors ${
321+ item . level === 1 ? 'font-medium text-gray-100' :
322+ item . level === 2 ? 'text-gray-300 pl-3' : 'text-gray-400 pl-6'
323+ } `}
324+ >
325+ { item . text }
326+ </ a >
327+ ) ) }
328+ </ nav >
299329 </ div >
300330 </ div >
301331
@@ -337,24 +367,24 @@ const WriteupDetail = () => {
337367 </ div >
338368 </ div >
339369 { /* Footer */ }
340- < footer className = "border-t border-gray-800 bg-black py-6" >
341- < div className = "max-w-6xl mx-auto px-6 text-center" >
342- < div className = "flex justify-center space-x-6 mb-4" >
343- < a href = "https://github.com/screensguard" target = "_blank" rel = "noopener noreferrer" className = "text-gray-400 hover:text-white transition-colors" >
344- < FontAwesomeIcon icon = { faGithub } size = "lg" />
345- </ a >
346- < a href = "https://ctftime.org/user/79947" target = "_blank" rel = "noopener noreferrer" className = "text-gray-400 hover:text-white transition-colors" >
347- < FontAwesomeIcon icon = { faFlag } size = "lg" />
348- </ a >
349- < a href = "https://x.com/Rudrakshsaini2" target = "_blank" rel = "noopener noreferrer" className = "text-gray-400 hover:text-white transition-colors" >
350- < FontAwesomeIcon icon = { faTwitter } size = "lg" />
351- </ a >
352- </ div >
353- < p className = "text-gray-400 text-sm" > © screenguard 2025. All rights reserved.</ p >
354- </ div >
355- </ footer >
370+ < footer className = "border-t border-gray-800 bg-black py-6" >
371+ < div className = "max-w-6xl mx-auto px-6 text-center" >
372+ < div className = "flex justify-center space-x-6 mb-4" >
373+ < a href = "https://github.com/screensguard" target = "_blank" rel = "noopener noreferrer" className = "text-gray-400 hover:text-white transition-colors" >
374+ < FontAwesomeIcon icon = { faGithub } size = "lg" />
375+ </ a >
376+ < a href = "https://ctftime.org/user/79947" target = "_blank" rel = "noopener noreferrer" className = "text-gray-400 hover:text-white transition-colors" >
377+ < FontAwesomeIcon icon = { faFlag } size = "lg" />
378+ </ a >
379+ < a href = "https://x.com/Rudrakshsaini2" target = "_blank" rel = "noopener noreferrer" className = "text-gray-400 hover:text-white transition-colors" >
380+ < FontAwesomeIcon icon = { faTwitter } size = "lg" />
381+ </ a >
382+ </ div >
383+ < p className = "text-gray-400 text-sm" > © screenguard 2025. All rights reserved.</ p >
384+ </ div >
385+ </ footer >
356386 </ div >
357387 ) ;
358388} ;
359389
360- export default WriteupDetail ;
390+ export default WriteupDetail ;
0 commit comments