Files
Nuxt-Content/components/content/ProseCode.vue
2025-07-22 17:46:39 +08:00

111 lines
2.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="relative group">
<pre ref="codeBlock"
:class="[`language-${language}`, 'overflow-x-auto']"
><code :class="`language-${language}`"><slot /></code></pre>
<button
@click="copyCode"
class="copy-button"
:class="{ 'copied': copied }"
type="button"
>
<span v-if="!copied" class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2" />
</svg>
复制
</span>
<span v-else class="flex items-center text-green-400">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
已复制
</span>
</button>
</div>
</template>
<script setup>
const props = defineProps({
code: {
type: String,
default: ''
},
language: {
type: String,
default: 'plaintext'
},
filename: {
type: String,
default: ''
}
})
const copied = ref(false)
const codeBlock = ref(null)
const copyCode = async () => {
const code = props.code || codeBlock.value?.querySelector('code')?.textContent || ''
await navigator.clipboard.writeText(code)
copied.value = true
setTimeout(() => {
copied.value = false
}, 2000)
}
</script>
<style scoped>
.copy-button {
position: absolute;
top: 0.5rem;
right: 0.5rem;
display: flex;
align-items: center;
padding: 0.375rem 0.5rem;
font-size: 0.75rem;
color: #ffffff;
background-color: rgba(55, 65, 81, 0.9);
border-radius: 0.375rem;
opacity: 0;
transition: all 0.2s ease;
z-index: 20;
cursor: pointer;
border: none;
outline: none;
}
.group:hover .copy-button {
opacity: 1;
}
.copy-button:hover {
background-color: rgba(55, 65, 81, 1);
transform: scale(1.05);
}
.copy-button.copied {
background-color: rgba(5, 150, 105, 0.9);
}
.copy-button.copied:hover {
background-color: rgba(5, 150, 105, 1);
}
pre {
margin: 0;
padding: 1rem;
border-radius: 0.5rem;
background-color: #1f2937;
overflow-x: auto;
}
pre code {
display: block;
padding-right: 2.5rem;
color: #e5e7eb;
font-size: 0.875rem;
line-height: 1.5;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
</style>