Nuxt Content で作ってるブログにある、コードブロックの内容をコピーできるボタンを用意した
Qiita とかを見てると、コードブロックの内容をコピーできるボタンが右上にくっついてることが多い。
けど僕のブログにはない。 よくない。
作ろう。
Override Default Component
https://github.com/nuxt/content/issues/1421#issuecomment-1218167791
./components/content/
配下にファイルを作成すると、
Nuxt Content で用意されている default の Component を上書きすることができる。
今回は
./components/content/ProseCode.vue
を作成した。
まずは雛形を作成
作成するにあたって、 https://github.com/nuxt/content/blob/main/src/runtime/components/Prose/ProseCode.vue の内容をコピーする。
<template lang="pug">
slot
</template>
<style lang="scss">
pre code .line {
display: block;
min-height: 1rem;
}
</style>
コピーボタンを用意する
コピーボタンを用意するにあたって、準備が必要である。 VueUse を使う。
ここでは、VueUse の useClipboard
を使う
<template lang="pug">
div.code-block
slot
button(@click="onClick")
</template>
<script lang="ts">
import { useClipboard } from '@vueuse/core';
const props = defineProps({
code: {
type: String,
default: ''
},
})
const { copy } = useClipboard();
const onClick = () => {
copy(props.code)
}
</script>
<style lang="scss">
.code-block {
pre {
padding-top: 2.1111111em !important;
code .line {
display: block;
min-height: 1rem;
}
}
}
</s>
これで終わり。
簡単な解説
useClipboard
から copy
を取得している。
copy は文字通り、コピーをしてくれる関数である。 引数にコピーしたい値を渡すと、クリップボードにコピーしてくれる。
ので、今回は props から受け取った code
を渡して、click event でコピーを実行するようにした。
以上。
せっかくなので色々やる
- ファイル名を表示
- ファイル名がない場合は、ファイルタイプを表示
- コピーボタンをホバーしたら、「コピーできるよー」ってテキストを表示
- コピーが完了したら、終わった旨を表示
<template lang="pug">
div.code-block.relative
span(
v-if="filename"
class="absolute top-0 py-2 px-4 text-xs text-gray-100 bg-zinc-500 dark:bg-gray-800 rounded-br-lg"
) {{ filename }}
span(
v-else-if="language"
class="absolute top-0 py-2 px-4 text-xs text-gray-100 bg-zinc-500 dark:bg-gray-800 rounded-br-lg"
) {{ language }}
slot
label(
class="absolute top-0 right-4 normal-case btn btn-ghost rounded-btn hover:text-rose-600 dark:hover:text-sky-300 hover:bg-inherit"
ref='btn'
@click="onClick"
)
span.mr-2(v-if="copied") Copied code!
span.mr-2(v-else-if="isHovered") Copy
font-awesome-icon(icon="copy" v-element-hover="onHover")
</template>
<script setup lang="ts">
import { useClipboard } from '@vueuse/core';
import { vElementHover } from "@vueuse/components"
const props = defineProps({
code: {
type: String,
default: ''
},
language: {
type: String,
default: ''
},
filename: {
type: String,
default: ''
}
})
const isHovered = ref(false)
function onHover(state: boolean) {
isHovered.value = state
}
const { copy, copied } = useClipboard();
const onClick = () => {
copy(props.code)
}
</script>
<style lang="scss">
.code-block {
pre {
padding-top: 2.1111111em !important;
code .line {
display: block;
min-height: 1rem;
}
}
}
</style>
簡単な解説
vueuse/components の vElementHover
を使って、
ホバーしたらうんぬんを実装した。
さらに props に filename や language を追加して、 それらがあったらうんぬんってのも実装した。
Nuxt Content の仕様で、
```language{number[]}[filename]
// JavaScript のコード
```
というのがある
name | value |
---|---|
language | コードの言語 |
number | ハイライトする行番号 {1,2,3}みたいな感じで指定 span タグに highlight ってクラスがつく |
filename | ファイル名 |
って感じです。
なので、今度時間ある時は highlight
class に style をつけなくちゃ
yasumemo
Markdown のコードブロックの中で、
```
をテキストで表示する方法
` 4つで書こうとできます。
ちなみにこれは 5つで囲って、その下に4つ、最後に3つです。
````md
```js
```
````
以上
おわりに
これが今回のコードです。
https://github.com/yanskun/blog/blob/main/components/content/ProseCode.vue