diff --git a/packages/components/src/components/code-block/code-block.stories.tsx b/packages/components/src/components/code-block/code-block.stories.tsx index b7dc7ca..418e510 100644 --- a/packages/components/src/components/code-block/code-block.stories.tsx +++ b/packages/components/src/components/code-block/code-block.stories.tsx @@ -464,3 +464,52 @@ export const WithCustomClassName: Story = { ), }; +export const TemplateLiteralSimple: Story = { + render: () => ( + + {` + echo hello + echo world + echo storybook + `} + + ), +}; +export const TemplateLiteralYaml: Story = { + render: () => ( + + {` + applications: + myapp: + source: + root: "/" + `} + + ), +}; +export const TemplateLiteralJavascript: Story = { + render: () => ( + + {` + function greet(name) { + console.log("Hello " + name); + } + + greet("Mintlify"); + `} + + ), +}; +export const TemplateLiteralWithEmptyLines: Story = { + render: () => ( + + {` + + npm install + + npm run build + + `} + + ), +}; diff --git a/packages/components/src/components/code-block/code-block.tsx b/packages/components/src/components/code-block/code-block.tsx index 61ac677..0f899cf 100644 --- a/packages/components/src/components/code-block/code-block.tsx +++ b/packages/components/src/components/code-block/code-block.tsx @@ -2,6 +2,7 @@ import type { ReactNode, RefObject } from "react"; import { Classes } from "@/constants/selectors"; import { cn } from "@/utils/cn"; +import { dedent } from "@/utils/dedent"; import { getNodeText } from "@/utils/get-node-text"; import type { CodeBlockTheme, CodeStyling } from "@/utils/shiki/code-styling"; @@ -98,7 +99,12 @@ const CodeBlock = function CodeBlock(params: CodeBlockProps) { copyButtonProps, } = params; - const codeString = getNodeText(children); + let codeString = getNodeText(children); + + if (typeof codeString === "string") { + codeString = dedent(codeString); + } + const hasGrayBackgroundContainer = !!filename || !!icon; return ( @@ -146,13 +152,16 @@ const CodeBlock = function CodeBlock(params: CodeBlockProps) { {askAiButton && askAiButton} )} + + > + {codeString} + ); }; diff --git a/packages/components/src/utils/dedent.ts b/packages/components/src/utils/dedent.ts new file mode 100644 index 0000000..7311d48 --- /dev/null +++ b/packages/components/src/utils/dedent.ts @@ -0,0 +1,25 @@ +const INDENT_REGEX = /^[ ]*/; + +export function dedent(code: string): string { + const lines = code.split("\n"); + + while (lines.length && lines[0].trim() === "") { + lines.shift(); + } + + while (lines.length && lines.at(-1)?.trim() === "") { + lines.pop(); + } + + if (lines.length === 0) { + return ""; + } + + const indents = lines + .filter((line) => line.trim().length > 0) + .map((line) => line.match(INDENT_REGEX)?.[0].length ?? 0); + + const minIndent = Math.min(...indents); + + return lines.map((line) => line.slice(minIndent)).join("\n"); +} \ No newline at end of file