@gmickel/gno 0.27.1 → 0.27.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -8,14 +8,15 @@ import {
|
|
|
8
8
|
useRef,
|
|
9
9
|
useState,
|
|
10
10
|
} from "react";
|
|
11
|
-
import {
|
|
11
|
+
import { codeToHtml, type ShikiTransformer } from "shiki";
|
|
12
12
|
|
|
13
|
+
import { resolveCodeLanguage } from "../../lib/code-language";
|
|
13
14
|
import { cn } from "../../lib/utils";
|
|
14
15
|
import { Button } from "../ui/button";
|
|
15
16
|
|
|
16
17
|
type CodeBlockProps = HTMLAttributes<HTMLDivElement> & {
|
|
17
18
|
code: string;
|
|
18
|
-
language:
|
|
19
|
+
language: string;
|
|
19
20
|
showLineNumbers?: boolean;
|
|
20
21
|
highlightedLines?: number[];
|
|
21
22
|
scrollToLine?: number;
|
|
@@ -78,27 +79,43 @@ function createLineTransformer(
|
|
|
78
79
|
|
|
79
80
|
export async function highlightCode(
|
|
80
81
|
code: string,
|
|
81
|
-
language:
|
|
82
|
+
language: string,
|
|
82
83
|
showLineNumbers = false,
|
|
83
84
|
highlightedLines: number[] = []
|
|
84
85
|
) {
|
|
86
|
+
const resolvedLanguage = resolveCodeLanguage(language);
|
|
85
87
|
const transformers: ShikiTransformer[] =
|
|
86
88
|
showLineNumbers || highlightedLines.length > 0
|
|
87
89
|
? [createLineTransformer(showLineNumbers, highlightedLines)]
|
|
88
90
|
: [];
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
92
|
+
try {
|
|
93
|
+
return await Promise.all([
|
|
94
|
+
codeToHtml(code, {
|
|
95
|
+
lang: resolvedLanguage,
|
|
96
|
+
theme: "one-light",
|
|
97
|
+
transformers,
|
|
98
|
+
}),
|
|
99
|
+
codeToHtml(code, {
|
|
100
|
+
lang: resolvedLanguage,
|
|
101
|
+
theme: "one-dark-pro",
|
|
102
|
+
transformers,
|
|
103
|
+
}),
|
|
104
|
+
]);
|
|
105
|
+
} catch {
|
|
106
|
+
return await Promise.all([
|
|
107
|
+
codeToHtml(code, {
|
|
108
|
+
lang: "text",
|
|
109
|
+
theme: "one-light",
|
|
110
|
+
transformers,
|
|
111
|
+
}),
|
|
112
|
+
codeToHtml(code, {
|
|
113
|
+
lang: "text",
|
|
114
|
+
theme: "one-dark-pro",
|
|
115
|
+
transformers,
|
|
116
|
+
}),
|
|
117
|
+
]);
|
|
118
|
+
}
|
|
102
119
|
}
|
|
103
120
|
|
|
104
121
|
export const CodeBlock = ({
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { ComponentProps, FC, ReactNode } from "react";
|
|
9
|
-
import type { BundledLanguage } from "shiki";
|
|
10
9
|
|
|
11
10
|
import { ExternalLinkIcon } from "lucide-react";
|
|
12
11
|
import { memo } from "react";
|
|
@@ -14,6 +13,10 @@ import ReactMarkdown from "react-markdown";
|
|
|
14
13
|
import rehypeSanitize from "rehype-sanitize";
|
|
15
14
|
import remarkGfm from "remark-gfm";
|
|
16
15
|
|
|
16
|
+
import {
|
|
17
|
+
extractMarkdownCodeLanguage,
|
|
18
|
+
resolveCodeLanguage,
|
|
19
|
+
} from "../../lib/code-language";
|
|
17
20
|
import { cn } from "../../lib/utils";
|
|
18
21
|
import { CodeBlock, CodeBlockCopyButton } from "../ai-elements/code-block";
|
|
19
22
|
|
|
@@ -106,8 +109,7 @@ const Pre: FC<ComponentProps<"pre">> = ({ children, ...props }) => {
|
|
|
106
109
|
const code = String(codeElement.props.children ?? "").trim();
|
|
107
110
|
|
|
108
111
|
// Extract language from className (e.g., "language-typescript")
|
|
109
|
-
const
|
|
110
|
-
const language = (match?.[1] ?? "plaintext") as BundledLanguage;
|
|
112
|
+
const language = resolveCodeLanguage(extractMarkdownCodeLanguage(className));
|
|
111
113
|
|
|
112
114
|
return (
|
|
113
115
|
<div className="group/code my-4">
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { bundledLanguages, type BundledLanguage } from "shiki";
|
|
2
|
+
|
|
3
|
+
export type CodeLanguage = BundledLanguage | "text";
|
|
4
|
+
|
|
5
|
+
const LANGUAGE_CLASS_PATTERN = /language-([A-Za-z0-9_+-]+)/;
|
|
6
|
+
|
|
7
|
+
const LANGUAGE_ALIASES = {
|
|
8
|
+
cjs: "javascript",
|
|
9
|
+
js: "javascript",
|
|
10
|
+
md: "markdown",
|
|
11
|
+
mts: "typescript",
|
|
12
|
+
plain: "text",
|
|
13
|
+
plaintext: "text",
|
|
14
|
+
py: "python",
|
|
15
|
+
shell: "bash",
|
|
16
|
+
tasks: "markdown",
|
|
17
|
+
text: "text",
|
|
18
|
+
ts: "typescript",
|
|
19
|
+
txt: "text",
|
|
20
|
+
yml: "yaml",
|
|
21
|
+
zsh: "bash",
|
|
22
|
+
} as const satisfies Record<string, CodeLanguage>;
|
|
23
|
+
|
|
24
|
+
export function extractMarkdownCodeLanguage(
|
|
25
|
+
className: string | undefined
|
|
26
|
+
): string {
|
|
27
|
+
return className?.match(LANGUAGE_CLASS_PATTERN)?.[1]?.toLowerCase() ?? "text";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function resolveCodeLanguage(
|
|
31
|
+
language: string | null | undefined
|
|
32
|
+
): CodeLanguage {
|
|
33
|
+
const normalized = language?.trim().toLowerCase();
|
|
34
|
+
if (!normalized) {
|
|
35
|
+
return "text";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const aliased =
|
|
39
|
+
LANGUAGE_ALIASES[normalized as keyof typeof LANGUAGE_ALIASES] ?? normalized;
|
|
40
|
+
if (aliased === "text") {
|
|
41
|
+
return "text";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (aliased in bundledLanguages) {
|
|
45
|
+
return aliased as BundledLanguage;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return "text";
|
|
49
|
+
}
|