CodeBlock.vue 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <template>
  2. <div :class="['code-block', themeClass]">
  3. <pre><code :class="[language, 'hljs']" v-html="highlightedCode" /></pre>
  4. <v-btn
  5. icon="fas fa-copy"
  6. variant="tonal"
  7. aria-label="Copy the content to the clipboard"
  8. class="text-primary"
  9. @click="copyCode"
  10. />
  11. </div>
  12. <v-snackbar v-model="showConfirmation" color="success" :timeout="2000">
  13. Content copied to clipboard
  14. </v-snackbar>
  15. </template>
  16. <script setup lang="ts">
  17. import { ref } from 'vue'
  18. import hljs from 'highlight.js'
  19. const props = defineProps({
  20. code: String,
  21. language: {
  22. type: String,
  23. required: false,
  24. default: 'php'
  25. }
  26. })
  27. import {useTheme} from "vuetify";
  28. const theme = useTheme()
  29. const themeClass = computed(() => theme.name.value)
  30. const highlightedCode = ref(props.code)
  31. watch(() => props.code, (newVal) => {
  32. if (newVal) {
  33. highlightedCode.value = hljs.highlightAuto(newVal).value;
  34. }
  35. }, { immediate: true });
  36. let copyCode = () => { console.error('clipboard is not available')}
  37. const showConfirmation = ref(false)
  38. onMounted(() => {
  39. copyCode = async () => {
  40. try {
  41. await navigator.clipboard.writeText(props.code);
  42. showConfirmation.value = true
  43. } catch (err) {
  44. console.error('Failed to copy text: ', err);
  45. }
  46. }
  47. })
  48. </script>
  49. <style lang="scss">
  50. // /!\ Warning: `scoped` attribute break the highlight js style, do not add here (no harm though)
  51. @use "sass:meta";
  52. .code-block {
  53. display: flex;
  54. flex-direction: row;
  55. margin: 24px;
  56. background: rgba(var(--v-theme-code-background));
  57. border-radius: 4px;
  58. * {
  59. background: transparent !important;
  60. }
  61. pre {
  62. flex: 1;
  63. }
  64. code {
  65. white-space: pre-wrap;
  66. }
  67. @media (max-width: 600px) {
  68. margin: 24px 6px;
  69. }
  70. }
  71. .light {
  72. @include meta.load-css("highlight.js/styles/stackoverflow-light");
  73. }
  74. .dark {
  75. @include meta.load-css("highlight.js/styles/stackoverflow-dark");
  76. }
  77. // no syntax coloration with shell language
  78. .shell {
  79. * {
  80. color: rgba(var(--v-theme-on-code-background)) !important;
  81. }
  82. }
  83. </style>