feat: add copy code element

pull/658/head
Divyansh Singh 3 years ago
parent 607c3d33f3
commit e8125439b3

@ -1,6 +1,7 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useData } from 'vitepress'
import { useCopyCode } from '../composables/copy-code'
import { useSidebar } from '../composables/sidebar'
import VPDocAside from './VPDocAside.vue'
import VPDocFooter from './VPDocFooter.vue'
@ -11,6 +12,8 @@ const { hasSidebar } = useSidebar()
const pageName = computed(() => {
return page.value.relativePath.slice(0, page.value.relativePath.indexOf('/'))
})
useCopyCode()
</script>
<template>

@ -0,0 +1,42 @@
import { nextTick, watch } from 'vue'
import { inBrowser, useData } from 'vitepress'
const handleElement = (el: HTMLElement) => {
el.onclick = () => {
const parent = el.parentElement
if (!parent) return
const isShell =
parent.classList.contains('language-sh') ||
parent.classList.contains('language-bash')
let { innerText: text = '' } = parent
if (isShell) text = text.replace(/^ *\$ /gm, '')
navigator.clipboard.writeText(text).then(() => {
el.classList.add('copied')
setTimeout(() => {
el.classList.remove('copied')
}, 800)
})
}
}
export function useCopyCode() {
const { page } = useData()
if (inBrowser)
watch(
() => page.value.relativePath,
() => {
nextTick(() => {
document
.querySelectorAll<HTMLSpanElement>(
'.vp-doc div[class*="language-"]>span.copy'
)
.forEach(handleElement)
})
},
{ immediate: true, flush: 'post' }
)
}

@ -366,6 +366,29 @@
transition: border-color 0.5s, color 0.5s;
}
.vp-doc [class*='language-'] > span.copy:before {
position: absolute;
top: 8px;
right: 8px;
z-index: 2;
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(235,235,235,0.38)' stroke-width='2' class='h-6 w-6' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2'/%3E%3C/svg%3E");
opacity: 0;
cursor: pointer;
transition: opacity 0.5s;
}
.vp-doc [class*='language-'] > span.copied:before {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(235,235,235,0.38)' stroke-width='2' class='h-6 w-6' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E");
}
.vp-doc [class*='language-']:hover > span.copy:before {
opacity: 1;
}
.vp-doc [class*='language-']:hover:before {
opacity: 0;
}
.vp-doc [class*='language-']:before {
position: absolute;
top: 6px;
@ -374,7 +397,7 @@
font-size: 12px;
font-weight: 500;
color: var(--vp-c-text-dark-3);
transition: color 0.5s;
transition: color 0.5s, opacity 0.5s;
}
.vp-doc [class~='language-c']:before { content: 'c'; }

@ -15,6 +15,6 @@ export const preWrapperPlugin = (md: MarkdownIt) => {
const [tokens, idx] = args
const token = tokens[idx]
const rawCode = fence(...args)
return `<div class="language-${token.info.trim()}">${rawCode}</div>`
return `<div class="language-${token.info.trim()}"><span class="copy" />${rawCode}</div>`
}
}

Loading…
Cancel
Save