mirror of
https://codeberg.org/Freedium-cfd/web.git
synced 2026-03-11 09:04:37 +00:00
feature(shiki): make codeblock text cursor selectable
This commit is contained in:
parent
20d94cf83d
commit
6ad835d89f
2 changed files with 67 additions and 33 deletions
|
|
@ -143,4 +143,8 @@ html {
|
|||
html.dark pre.shiki .diff.remove {
|
||||
background-color: hsla(0 62.8% 30.6% / 0.7);
|
||||
}
|
||||
|
||||
pre.shiki code {
|
||||
@apply select-text cursor-text focus:outline-none;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { mdsvex, escapeSvelte } from 'mdsvex';
|
||||
import rehypeExternalLinks from 'rehype-external-links';
|
||||
import { createHighlighter } from 'shiki';
|
||||
import adapter from '@sveltejs/adapter-auto';
|
||||
import { toHtml } from 'hast-util-to-html';
|
||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||
import { h } from 'hastscript';
|
||||
import remarkMixtapeEmbed from './src/lib/utils/remark/mixtape-embed.js';
|
||||
import { mdsvex, escapeSvelte } from "mdsvex";
|
||||
import rehypeExternalLinks from "rehype-external-links";
|
||||
import { createHighlighter } from "shiki";
|
||||
import adapter from "@sveltejs/adapter-auto";
|
||||
import { toHtml } from "hast-util-to-html";
|
||||
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
|
||||
import { h } from "hastscript";
|
||||
import remarkMixtapeEmbed from "./src/lib/utils/remark/mixtape-embed.js";
|
||||
|
||||
const readySvg =
|
||||
"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24'><path fill='none' stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M8.25 7.5V6.108c0-1.135.845-2.098 1.976-2.192q.56-.045 1.124-.08M15.75 18H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48 48 0 0 0-1.123-.08M15.75 18.75v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5A3.375 3.375 0 0 0 6.375 7.5H5.25m11.9-3.664A2.25 2.25 0 0 0 15 2.25h-1.5a2.25 2.25 0 0 0-2.15 1.586m5.8 0q.099.316.1.664v.75h-6V4.5q.001-.348.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5a9 9 0 0 0-9-9'/></svg>";
|
||||
|
|
@ -16,9 +16,9 @@ const successSvg =
|
|||
export function renderCodeCopyButton(code, options = {}) {
|
||||
const toggleMs = options.toggle || 3000;
|
||||
const button = h(
|
||||
'button',
|
||||
"button",
|
||||
{
|
||||
'data-code': code,
|
||||
"data-code": code,
|
||||
style: `
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
|
|
@ -54,11 +54,11 @@ export function renderCodeCopyButton(code, options = {}) {
|
|||
success.style.display = 'none';
|
||||
}, ${toggleMs});
|
||||
window.dispatchEvent(new CustomEvent('toast', { detail: { message: 'Copied to clipboard' } }));
|
||||
`
|
||||
`,
|
||||
},
|
||||
[
|
||||
h('span', {
|
||||
class: 'ready',
|
||||
h("span", {
|
||||
class: "ready",
|
||||
style: `
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
|
|
@ -68,10 +68,10 @@ export function renderCodeCopyButton(code, options = {}) {
|
|||
background-image: url("${readySvg}");
|
||||
z-index: 99;
|
||||
display: block;
|
||||
`
|
||||
`,
|
||||
}),
|
||||
h('span', {
|
||||
class: 'success',
|
||||
h("span", {
|
||||
class: "success",
|
||||
style: `
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
|
|
@ -81,9 +81,9 @@ export function renderCodeCopyButton(code, options = {}) {
|
|||
background-image: url("${successSvg}");
|
||||
z-index: 99;
|
||||
display: none;
|
||||
`
|
||||
})
|
||||
]
|
||||
`,
|
||||
}),
|
||||
],
|
||||
);
|
||||
|
||||
return toHtml(button);
|
||||
|
|
@ -91,35 +91,65 @@ export function renderCodeCopyButton(code, options = {}) {
|
|||
|
||||
/** @type {import('mdsvex').MdsvexOptions} */
|
||||
const mdsvexOptions = {
|
||||
extensions: ['.md'],
|
||||
extensions: [".md"],
|
||||
remarkPlugins: [remarkMixtapeEmbed],
|
||||
rehypePlugins: [[rehypeExternalLinks, { target: '_blank', rel: ['nofollow'] }]],
|
||||
rehypePlugins: [
|
||||
[rehypeExternalLinks, { target: "_blank", rel: ["nofollow"] }],
|
||||
],
|
||||
highlight: {
|
||||
highlighter: async (code, lang = 'text') => {
|
||||
highlighter: async (code, lang = "text") => {
|
||||
const highlighter = await createHighlighter({
|
||||
themes: ['poimandres'],
|
||||
langs: ['javascript', 'typescript']
|
||||
themes: ["poimandres"],
|
||||
langs: ["javascript", "typescript"],
|
||||
});
|
||||
await highlighter.loadLanguage('javascript', 'typescript');
|
||||
const result = highlighter.codeToHtml(code, {
|
||||
await highlighter.loadLanguage("javascript", "typescript");
|
||||
const result = highlighter.codeToHast(code, {
|
||||
lang,
|
||||
theme: 'poimandres'
|
||||
theme: "poimandres",
|
||||
transformers: [
|
||||
{
|
||||
code(node) {
|
||||
node.properties = {
|
||||
...node.properties,
|
||||
contenteditable: "true",
|
||||
"aria-label": "code",
|
||||
"aria-readonly": "true",
|
||||
inputmode: "none",
|
||||
tabindex: "0",
|
||||
"aria-multiline": "true",
|
||||
"aria-haspopup": "false",
|
||||
"data-gramm": "false",
|
||||
"data-gramm_editor": "false",
|
||||
"data-enable-grammarly": "false",
|
||||
spellcheck: "false",
|
||||
autocorrect: "off",
|
||||
autocapitalize: "none",
|
||||
autocomplete: "off",
|
||||
"data-ms-editor": "false",
|
||||
};
|
||||
return node;
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const resultHtml = toHtml(result);
|
||||
const buttonHtml = renderCodeCopyButton(code, { toggle: 1200 });
|
||||
const html = escapeSvelte(`<div class="relative">${buttonHtml}${result}</div>`);
|
||||
const html = escapeSvelte(
|
||||
`<div class="relative">${buttonHtml}${resultHtml}</div>`,
|
||||
);
|
||||
return `{@html \`${html}\` }`;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
extensions: ['.svelte', '.md'],
|
||||
extensions: [".svelte", ".md"],
|
||||
preprocess: [vitePreprocess(), mdsvex(mdsvexOptions)],
|
||||
|
||||
kit: {
|
||||
adapter: adapter()
|
||||
}
|
||||
adapter: adapter(),
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
|
|||
Loading…
Reference in a new issue