@gmickel/gno 0.27.0 → 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gmickel/gno",
3
- "version": "0.27.0",
3
+ "version": "0.27.3",
4
4
  "description": "Local semantic search for your documents. Index Markdown, PDF, and Office files with hybrid BM25 + vector search.",
5
5
  "keywords": [
6
6
  "embeddings",
@@ -8,14 +8,15 @@ import {
8
8
  useRef,
9
9
  useState,
10
10
  } from "react";
11
- import { type BundledLanguage, codeToHtml, type ShikiTransformer } from "shiki";
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: BundledLanguage;
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: BundledLanguage,
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
- return await Promise.all([
91
- codeToHtml(code, {
92
- lang: language,
93
- theme: "one-light",
94
- transformers,
95
- }),
96
- codeToHtml(code, {
97
- lang: language,
98
- theme: "one-dark-pro",
99
- transformers,
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 match = /language-(\w+)/.exec(className);
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
+ }
@@ -1423,7 +1423,8 @@ export async function handleCreateDoc(
1423
1423
  await atomicWrite(fullPath, contentToWrite);
1424
1424
 
1425
1425
  // Build gno:// URI for the created document
1426
- const gnoUri = `gno://${collection.name}/${normalizedRelPath}`;
1426
+ const posixRelPath = normalizedRelPath.split(nodePath.sep).join("/");
1427
+ const gnoUri = `gno://${collection.name}/${posixRelPath}`;
1427
1428
 
1428
1429
  // Run sync via job system (non-blocking)
1429
1430
  // Note: embedding handled separately by embed-scheduler (not inline)