chatgpt-web/src/lib/Code.svelte

109 lines
2.6 KiB
Svelte

<script lang="ts">
import { Highlight } from 'svelte-highlight'
// Import both dark and light styles
import { github, githubDark } from 'svelte-highlight/styles'
// Style depends on system theme
const style = window.matchMedia('(prefers-color-scheme: dark)').matches ? githubDark : github
// Copy function for the code block
import copy from 'copy-to-clipboard'
// Import all supported languages
import {
javascript,
python,
typescript,
ruby,
go,
java,
sql,
shell,
php,
plaintext,
type LanguageType
} from 'svelte-highlight/languages'
export const type: 'code' = 'code'
export const raw: string = ''
export const codeBlockStyle: 'indented' | undefined = undefined
export let lang: string | undefined
export let text: string
// Map lang string to LanguageType
let language: LanguageType<string>
switch (lang) {
case 'js':
case 'javascript':
language = javascript
break
case 'py':
case 'python':
language = python
break
case 'ts':
case 'typescript':
language = typescript
break
case 'rb':
case 'ruby':
language = ruby
break
case 'go':
case 'golang':
language = go
break
case 'java':
language = java
break
case 'sql':
language = sql
break
case 'sh':
case 'shell':
case 'bash':
language = shell
break
case 'php':
language = php
break
default:
language = plaintext
}
// For copying code - reference: https://vyacheslavbasharov.com/blog/adding-click-to-copy-code-markdown-blog
const copyFunction = (event) => {
// Get the button the user clicked on
const clickedElement = event.target as HTMLButtonElement
// Get the next element
const nextElement = clickedElement.nextElementSibling
// Modify the appearance of the button
const originalButtonContent = clickedElement.innerHTML
clickedElement.classList.add('is-success')
clickedElement.innerHTML = 'Copied!'
// Retrieve the code in the code block
const codeBlock = (nextElement.querySelector('pre > code') as HTMLPreElement).innerText
copy(codeBlock)
// Restored the button after copying the text in 1 second.
setTimeout(() => {
clickedElement.innerHTML = originalButtonContent
clickedElement.classList.remove('is-success')
clickedElement.blur()
}, 1000)
}
</script>
<svelte:head>
{@html style}
</svelte:head>
<div class="code-block is-relative">
<button class="button is-light is-outlined is-small p-2" on:click={copyFunction}>Copy</button>
<Highlight code={text} {language} />
</div>