openpanel/documentation/src/refine-theme/common-codeblock-string.tsx
2024-02-05 10:23:04 +01:00

181 lines
6.3 KiB
TypeScript

import { usePrismTheme, useThemeConfig } from "@docusaurus/theme-common";
import {
containsLineNumbers,
parseCodeBlockTitle,
parseLanguage,
parseLines,
useCodeWordWrap,
} from "@docusaurus/theme-common/internal";
import Line from "@theme/CodeBlock/Line";
import clsx from "clsx";
import Highlight, { defaultProps } from "prism-react-renderer";
import React from "react";
import { CommonCodeBlockContainer } from "./common-codeblock-container";
import { CommonCopyButton } from "./common-copy-button";
import { CommonWordWrapButton } from "./common-wordwrap-button";
const DefaultDocumentIcon = (props: React.SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={12}
height={14}
viewBox="0 0 12 14"
fill="none"
{...props}
>
<path
fill="currentColor"
fillRule="evenodd"
d="M11 4.994V11.6A1.4 1.4 0 0 1 9.6 13H2.4A1.4 1.4 0 0 1 1 11.6V2.4A1.4 1.4 0 0 1 2.4 1h4.606a1.4 1.4 0 0 1 .99.41l2.594 2.594a1.4 1.4 0 0 1 .41.99ZM0 2.4A2.4 2.4 0 0 1 2.4 0h4.606a2.4 2.4 0 0 1 1.697.703l2.594 2.594A2.4 2.4 0 0 1 12 4.994V11.6A2.4 2.4 0 0 1 9.6 14H2.4A2.4 2.4 0 0 1 0 11.6V2.4ZM3.5 6a.5.5 0 0 0 0 1h5a.5.5 0 0 0 0-1h-5Zm0 2a.5.5 0 0 0 0 1h5a.5.5 0 0 0 0-1h-5Zm0 2a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1h-3Z"
clipRule="evenodd"
/>
</svg>
);
const CodeBlockTitle = ({
children,
icon = <DefaultDocumentIcon />,
}: {
children?: React.ReactNode;
icon?: React.ReactNode;
}) => {
return (
<div
className={clsx(
"py-3",
"px-4",
"bg-gray-100 dark:bg-gray-700",
"text-gray-800",
"dark:text-gray-100",
"text-xs",
"flex items-center",
"gap-2",
"rounded-tl-lg",
"rounded-tr-lg",
)}
>
{icon}
{children}
</div>
);
};
export const CodeBlockString = ({
children,
className: blockClassName = "",
metastring,
title: titleProp,
showLineNumbers: showLineNumbersProp,
language: languageProp,
icon,
style,
}) => {
const {
prism: { defaultLanguage, magicComments },
} = useThemeConfig();
const language =
languageProp ?? parseLanguage(blockClassName) ?? defaultLanguage;
const prismTheme = usePrismTheme();
const wordWrap = useCodeWordWrap();
// We still parse the metastring in case we want to support more syntax in the
// future. Note that MDX doesn't strip quotes when parsing metastring:
// "title=\"xyz\"" => title: "\"xyz\""
const title = parseCodeBlockTitle(metastring) || titleProp;
const { lineClassNames, code } = parseLines(children, {
metastring,
language,
magicComments,
});
const showLineNumbers =
showLineNumbersProp ?? containsLineNumbers(metastring);
return (
<CommonCodeBlockContainer
as="div"
className={clsx(
"refine-common-code-block",
language && `language-${language}`,
"rounded-lg",
"bg-refine-react-light-code",
"dark:bg-refine-react-dark-code",
"border",
"border-gray-300",
"dark:border-0",
"mb-6",
"relative",
"refine-wider-container",
)}
style={style}
>
{title && <CodeBlockTitle icon={icon}>{title}</CodeBlockTitle>}
<div className={clsx("relative", "pt-3", "pb-0", "not-prose")}>
<Highlight
{...defaultProps}
theme={prismTheme}
code={code}
language={language ?? "text"}
>
{({ className, tokens, getLineProps, getTokenProps }) => (
<pre
tabIndex={0}
ref={wordWrap.codeBlockRef}
className={clsx(
className,
"bg-transparent",
"!mt-0",
"!mb-0",
"m-0",
"px-0",
"pt-0",
"font-jetBrains-mono",
"pb-3",
)}
>
<code
className={clsx(
"font-[inherit]",
"bg-transparent",
"inline-block",
"min-w-full",
)}
>
{tokens.map((line, i) => (
<Line
key={i}
line={line}
getLineProps={getLineProps}
getTokenProps={getTokenProps}
classNames={clsx(
lineClassNames[i],
"px-4",
"text-xs sm:text-sm 2xl:text-sm",
)}
showLineNumbers={showLineNumbers}
/>
))}
</code>
</pre>
)}
</Highlight>
</div>
<div
className={clsx(
"absolute",
title ? "top-2 right-2" : "top-3 right-3",
"flex items-center gap-2",
)}
>
{(wordWrap.isEnabled || wordWrap.isCodeScrollable) && (
<CommonWordWrapButton
onClick={wordWrap.toggle}
isEnabled={wordWrap.isEnabled}
/>
)}
<CommonCopyButton className={clsx()} code={code} />
</div>
</CommonCodeBlockContainer>
);
};