@@ -243,6 +243,22 @@ const canonicalUrl = computed(() => {
243243 return url
244244})
245245
246+ // Toggle markdown view mode
247+ const markdownViewModes = [
248+ {
249+ key: ' preview' ,
250+ label: $t (' code.markdown_view_mode.preview' ),
251+ icon: ' i-carbon-view' ,
252+ },
253+ {
254+ key: ' code' ,
255+ label: $t (' code.markdown_view_mode.code' ),
256+ icon: ' i-carbon-code' ,
257+ },
258+ ] as const
259+
260+ const markdownViewMode = ref <(typeof markdownViewModes )[number ][' key' ]>(' preview' )
261+
246262useHead ({
247263 link: [{ rel: ' canonical' , href: canonicalUrl }],
248264})
@@ -359,15 +375,39 @@ useSeoMeta({
359375 <!-- File viewer -->
360376 <template v-if =" isViewingFile && fileContent " >
361377 <div
362- class =" sticky top-0 bg-bg border-b border-border px-4 py-2 flex items-center justify-between"
378+ class =" sticky z-10 top-0 bg-bg border-b border-border px-4 py-2 flex items-center justify-between"
363379 >
364- <div class =" flex items-center gap-3 text-sm" >
365- <span class =" text-fg-muted" >{{
366- $t('code.lines', { count: fileContent.lines })
367- }}</span >
368- <span v-if =" currentNode?.size" class =" text-fg-subtle" >{{
369- formatBytes(currentNode.size)
370- }}</span >
380+ <div class =" flex items-center gap-2" >
381+ <div
382+ v-if =" fileContent.markdownHtml"
383+ class =" flex items-center gap-1 p-0.5 bg-bg-subtle border border-border-subtle rounded-md overflow-x-auto"
384+ role =" tablist"
385+ aria-label =" Markdown view mode selector"
386+ >
387+ <button
388+ v-for =" mode in markdownViewModes"
389+ :key =" mode.key"
390+ role =" tab"
391+ class =" px-2 py-1.5 font-mono text-xs rounded transition-colors duration-150 border border-solid focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 inline-flex items-center gap-1.5"
392+ :class ="
393+ markdownViewMode === mode.key
394+ ? 'bg-bg shadow text-fg border-border'
395+ : 'text-fg-subtle hover:text-fg border-transparent'
396+ "
397+ @click =" markdownViewMode = mode.key"
398+ >
399+ <span class =" inline-block h-3 w-3" :class =" mode.icon" aria-hidden =" true" />
400+ {{ mode.label }}
401+ </button >
402+ </div >
403+ <div class =" flex items-center gap-3 text-sm" >
404+ <span class =" text-fg-muted" >{{
405+ $t('code.lines', { count: fileContent.lines })
406+ }}</span >
407+ <span v-if =" currentNode?.size" class =" text-fg-subtle" >{{
408+ formatBytes(currentNode.size)
409+ }}</span >
410+ </div >
371411 </div >
372412 <div class =" flex items-center gap-2" >
373413 <button
@@ -389,7 +429,19 @@ useSeoMeta({
389429 </a >
390430 </div >
391431 </div >
432+ <div
433+ v-if =" fileContent.markdownHtml"
434+ v-show =" markdownViewMode === 'preview'"
435+ class =" flex justify-center p-4"
436+ >
437+ <div
438+ class =" readme-content prose prose-invert max-w-[70ch]"
439+ v-html =" fileContent.markdownHtml.html"
440+ ></div >
441+ </div >
442+
392443 <CodeViewer
444+ v-show =" !fileContent.markdownHtml || markdownViewMode === 'code'"
393445 :html =" fileContent.html"
394446 :lines =" fileContent.lines"
395447 :selected-lines =" selectedLines"
0 commit comments