feat: Add showLineNumbers prop to Snippet component
This commit is contained in:
parent
3f6d324980
commit
8bf5c5de40
@ -6,8 +6,19 @@ import { Fragment, useMemo } from "react";
|
||||
import { toast } from "react-toastify";
|
||||
import { Button } from "./Button";
|
||||
import Prism from "prismjs";
|
||||
import clsx from "clsx";
|
||||
|
||||
export default function CSRFence({ children, language }: { children: string; language: string }) {
|
||||
export default function CSRSnippet({
|
||||
children,
|
||||
language,
|
||||
label,
|
||||
showLineNumbers = false,
|
||||
}: {
|
||||
children: string;
|
||||
language: string;
|
||||
label?: string;
|
||||
showLineNumbers?: boolean;
|
||||
}) {
|
||||
const { theme } = useTheme();
|
||||
|
||||
const prismTheme = useMemo(() => {
|
||||
@ -23,25 +34,43 @@ export default function CSRFence({ children, language }: { children: string; lan
|
||||
<>
|
||||
<Highlight code={children.trimEnd()} language={language} theme={prismTheme} prism={Prism}>
|
||||
{({ className, style, tokens, getTokenProps }) => (
|
||||
<pre className={className} style={style}>
|
||||
<code>
|
||||
{tokens.map((line, lineIndex) => (
|
||||
<Fragment key={lineIndex}>
|
||||
{line
|
||||
.filter((token) => !token.empty)
|
||||
.map((token, tokenIndex) => (
|
||||
<span key={tokenIndex} {...getTokenProps({ token })} />
|
||||
))}
|
||||
{"\n"}
|
||||
</Fragment>
|
||||
))}
|
||||
</code>
|
||||
</pre>
|
||||
<div className="relative w-full">
|
||||
{label && (
|
||||
<div className="absolute px-4 py-1 left-0 text-sm text-gray-700 dark:text-gray-200 italic w-full bg-gray-200 dark:bg-gray-700 rounded-t-xl">
|
||||
{label}
|
||||
</div>
|
||||
)}
|
||||
<pre className={clsx(className, { "pt-11": !!label })} style={style}>
|
||||
<code>
|
||||
{tokens.map((line, lineIndex) => (
|
||||
<Fragment key={lineIndex}>
|
||||
{showLineNumbers && (
|
||||
<span
|
||||
className="text-gray-400 dark:text-gray-500 text-right font-mono w-8 inline-block pr-4"
|
||||
style={{ userSelect: "none" }}
|
||||
>
|
||||
{lineIndex + 1}
|
||||
</span>
|
||||
)}
|
||||
{line
|
||||
.filter((token) => !token.empty)
|
||||
.map((token, tokenIndex) => (
|
||||
<span key={tokenIndex} {...getTokenProps({ token })} />
|
||||
))}
|
||||
{"\n"}
|
||||
</Fragment>
|
||||
))}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
</Highlight>
|
||||
|
||||
<Button
|
||||
className="absolute top-2 right-2 w-8 h-8 aspect-square opacity-0 group-hover:opacity-50 hover:opacity-100 transition-opacity"
|
||||
className={clsx(
|
||||
"absolute right-2 w-8 h-8 aspect-square opacity-0 group-hover:opacity-50 hover:opacity-100 transition-opacity",
|
||||
!!label ? "top-10" : "top-2",
|
||||
)}
|
||||
size="sm"
|
||||
variant="secondary"
|
||||
onClick={copyToClipboard}
|
||||
|
||||
@ -10,35 +10,59 @@ import { Fragment, useMemo } from "react";
|
||||
|
||||
const CSRSnippet = clientOnly(() => import("./CSRSnippet"));
|
||||
|
||||
function SSRSnippet({ language, children }: { language: string; children: string }) {
|
||||
function SSRSnippet({
|
||||
language,
|
||||
children,
|
||||
label,
|
||||
showLineNumbers = false,
|
||||
}: {
|
||||
language: string;
|
||||
children: string;
|
||||
label?: string;
|
||||
showLineNumbers?: boolean;
|
||||
}) {
|
||||
const { theme } = useTheme();
|
||||
|
||||
const prismTheme = useMemo(() => {
|
||||
return prismThemes[theme];
|
||||
}, [theme]);
|
||||
|
||||
return (
|
||||
<Highlight code={children.trimEnd()} language={language} theme={prismTheme} prism={Prism}>
|
||||
{({ className, style, tokens, getTokenProps }) => (
|
||||
<pre className={className} style={style}>
|
||||
<code>
|
||||
{tokens.map((line, lineIndex) => (
|
||||
<Fragment key={lineIndex}>
|
||||
{line
|
||||
.filter((token) => !token.empty)
|
||||
.map((token, tokenIndex) => (
|
||||
<span key={tokenIndex} {...getTokenProps({ token })} />
|
||||
))}
|
||||
{"\n"}
|
||||
</Fragment>
|
||||
))}
|
||||
</code>
|
||||
</pre>
|
||||
)}
|
||||
</Highlight>
|
||||
<>
|
||||
{label && <div className="text-sm text-gray-500 dark:text-gray-400 mb-2">{label}</div>}
|
||||
<Highlight code={children.trimEnd()} language={language} theme={prismTheme} prism={Prism}>
|
||||
{({ className, style, tokens, getTokenProps }) => (
|
||||
<pre className={className} style={style}>
|
||||
<code>
|
||||
{tokens.map((line, lineIndex) => (
|
||||
<Fragment key={lineIndex}>
|
||||
{line
|
||||
.filter((token) => !token.empty)
|
||||
.map((token, tokenIndex) => (
|
||||
<span key={tokenIndex} {...getTokenProps({ token })} />
|
||||
))}
|
||||
{"\n"}
|
||||
</Fragment>
|
||||
))}
|
||||
</code>
|
||||
</pre>
|
||||
)}
|
||||
</Highlight>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function Snippet({ path, language, label }: { path: string; language: string; label?: string }) {
|
||||
export function Snippet({
|
||||
path,
|
||||
language,
|
||||
label,
|
||||
showLineNumbers,
|
||||
}: {
|
||||
path: string;
|
||||
language: string;
|
||||
label?: string;
|
||||
showLineNumbers: boolean;
|
||||
}) {
|
||||
const { snippets } = useData<Data>();
|
||||
|
||||
const snippet = snippets.find((snippet) => snippet.path === path);
|
||||
@ -47,6 +71,7 @@ export function Snippet({ path, language, label }: { path: string; language: str
|
||||
const props = {
|
||||
language,
|
||||
label,
|
||||
showLineNumbers,
|
||||
children: snippet.content,
|
||||
};
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ Parlons dans un premier temps de la signature d'un reducer :
|
||||
|
||||
{% tab value="jsx" label="JSX" %}
|
||||
|
||||
{% snippet path="data/docs/react/usereducer/reducer-example.jsx" language="jsx" label="test" /%}
|
||||
{% snippet path="data/docs/react/usereducer/reducer-example.jsx" language="jsx" label="test" showLineNumbers=true /%}
|
||||
|
||||
{% /tab %}
|
||||
|
||||
|
||||
@ -83,44 +83,12 @@ const tags = {
|
||||
},
|
||||
label: { type: String },
|
||||
path: { type: String },
|
||||
showLineNumbers: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
// snippet: {
|
||||
// // render: Fence2,
|
||||
// attributes: {
|
||||
// language: {
|
||||
// type: String,
|
||||
// default: "auto",
|
||||
// },
|
||||
// label: { type: String },
|
||||
// description: { type: String },
|
||||
// path: { type: String },
|
||||
// },
|
||||
// async transform(node: any, config: any) {
|
||||
// const attributes = node.transformAttributes(config);
|
||||
|
||||
// const pathValue = attributes.path;
|
||||
|
||||
// let language = attributes.language ?? "auto";
|
||||
// let content = "";
|
||||
|
||||
// if (!pathValue) {
|
||||
// console.warn("No path provided for snippet tag");
|
||||
// } else {
|
||||
// const absolutePath = path.resolve(__dirname, pathValue);
|
||||
// // Read the file content
|
||||
// try {
|
||||
// content = await fs.readFile(absolutePath, "utf-8");
|
||||
// } catch (error) {
|
||||
// console.error("Error reading file:", error);
|
||||
// content = `Error reading file: ${absolutePath}`;
|
||||
// language = "plain";
|
||||
// }
|
||||
|
||||
// // return new Tag("fence2", { ...attributes, language, content, label: "Temp" });
|
||||
// }
|
||||
// },
|
||||
// },
|
||||
};
|
||||
|
||||
export default tags;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user