v1.10 新增: 基于 Shiki 的语法高亮,支持懒加载。从
@lark-ui/core/code 导入即可使用。
const greeting = "Hello, World!";
console.log(greeting);import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** 基础代码高亮(CodeHighlighted)示例 */
export function CodeHighlightedBasicDemo() {
return (
<DemoProvider>
<CodeHighlighted
code={`const greeting = "Hello, World!";
console.log(greeting);`}
lang="typescript"
/>
</DemoProvider>
);
}概览
基于 Shiki 的语法高亮器。借助 TextMate 语法支持 200 多种语言,提供浅色/深色双主题,并支持懒加载。通过独立入口(@lark-ui/core/code)导出,避免为不需要它的应用打包 Shiki。
安装
CodeHighlighted 通过独立入口导出,以避免为不需要它的应用打包 Shiki。
import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";重要: 请勿从主入口 @lark-ui/core 导入。否则即便不使用,
也会把 Shiki 打进你的产物包。
基本用法
用 ShikiProvider 包裹应用,只需配置一次 Shiki。
其内部所有 CodeHighlighted 组件将共享同一个 Shiki 实例。
import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
export function App() {
return (
<ShikiProvider
engine="javascript"
languages={["tsx", "typescript", "bash", "json"]}
>
{/* All CodeHighlighted components share the same Shiki instance */}
<CodeHighlighted code="const x = 1;" lang="typescript" />
</ShikiProvider>
);
}示例
语言
CodeHighlighted 通过 Shiki 支持 200 多种语言。请只加载你需要的语言。
TypeScript
interface User {
id: string;
name: string;
email: string;
}
async function fetchUser(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** 包含 interface 的 TypeScript 代码 */
export function CodeHighlightedTypeScriptDemo() {
return (
<DemoProvider>
<CodeHighlighted
code={`interface User {
id: string;
name: string;
email: string;
}
async function fetchUser(id: string): Promise<User> {
const response = await fetch(\`/api/users/\${id}\`);
return response.json();
}`}
lang="typescript"
/>
</DemoProvider>
);
}React / TSX
import { useState } from "react";
export function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
);
}import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** React/TSX 代码示例 */
export function CodeHighlightedReactDemo() {
return (
<DemoProvider>
<CodeHighlighted
code={`import { useState } from "react";
export function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
);
}`}
lang="tsx"
/>
</DemoProvider>
);
}Bash / Shell
# Install Lark
npm install @lark-ui/core
# Or with pnpm
pnpm add @lark-ui/core
# Start development server
pnpm devimport { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** Bash/shell 命令 */
export function CodeHighlightedBashDemo() {
return (
<DemoProvider>
<CodeHighlighted
code={`# Install Lark
npm install @lark-ui/core
# Or with pnpm
pnpm add @lark-ui/core
# Start development server
pnpm dev`}
lang="bash"
/>
</DemoProvider>
);
}JSON
{
"name": "@lark-ui/core",
"version": "1.9.0",
"dependencies": {
"react": "^19.0.0",
"shiki": "^4.0.0"
}
}import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** JSON 配置 */
export function CodeHighlightedJsonDemo() {
return (
<DemoProvider>
<CodeHighlighted
code={`{
"name": "@lark-ui/core",
"version": "1.9.0",
"dependencies": {
"react": "^19.0.0",
"shiki": "^4.0.0"
}
}`}
lang="json"
/>
</DemoProvider>
);
}CSS
.button {
background: var(--color-brand);
border-radius: 0.5rem;
padding: 0.5rem 1rem;
&:hover {
background: var(--color-brand-hover);
}
}import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** CSS 代码示例 */
export function CodeHighlightedCssDemo() {
return (
<DemoProvider>
<CodeHighlighted
code={`.button {
background: var(--color-brand);
border-radius: 0.5rem;
padding: 0.5rem 1rem;
&:hover {
background: var(--color-brand-hover);
}
}`}
lang="css"
/>
</DemoProvider>
);
}高亮行
使用 highlightLines(从 1 开始计数)突出显示指定的行。
function processData(items: string[]) {
// Filter out empty items
const filtered = items.filter(Boolean);
// Transform to uppercase (highlighted)
const transformed = filtered.map(item => item.toUpperCase());
// Return sorted result
return transformed.toSorted();
}import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** 高亮指定行 */
export function CodeHighlightedHighlightLinesDemo() {
return (
<DemoProvider>
<CodeHighlighted
code={`function processData(items: string[]) {
// Filter out empty items
const filtered = items.filter(Boolean);
// Transform to uppercase (highlighted)
const transformed = filtered.map(item => item.toUpperCase());
// Return sorted result
return transformed.toSorted();
}`}
lang="typescript"
highlightLines={[5, 6]}
/>
</DemoProvider>
);
}自定义高亮颜色
通过 CSS 变量 --lark-code-highlight-bg 自定义高亮颜色。
function greet(name: string) {
// This line is highlighted
console.log(`Hello, ${name}!`);
return name.toUpperCase();
}--lark-code-highlight-bg: hsla(220, 80%, 50%, 0.1)行号
使用 showLineNumbers 显示行号。
import { useState, useEffect } from "react";
export function useWindowSize() {
const [size, setSize] = useState({ width: 0, height: 0 });
useEffect(() => {
function handleResize() {
setSize({
width: window.innerWidth,
height: window.innerHeight,
});
}
handleResize();
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return size;
}import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** 显示行号 */
export function CodeHighlightedLineNumbersDemo() {
return (
<DemoProvider>
<CodeHighlighted
code={`import { useState, useEffect } from "react";
export function useWindowSize() {
const [size, setSize] = useState({ width: 0, height: 0 });
useEffect(() => {
function handleResize() {
setSize({
width: window.innerWidth,
height: window.innerHeight,
});
}
handleResize();
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return size;
}`}
lang="typescript"
showLineNumbers
/>
</DemoProvider>
);
}复制按钮
使用 showCopyButton 添加复制到剪贴板的按钮。
npm install @lark-ui/coreimport { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** 带复制按钮 */
export function CodeHighlightedCopyButtonDemo() {
return (
<DemoProvider>
<CodeHighlighted
code={`npm install @lark-ui/core`}
lang="bash"
showCopyButton
/>
</DemoProvider>
);
}纯文本
在另一个容器内嵌入高亮代码时,使用 variant="plain" 可去掉外层表面、边框和圆角。
type EmbeddedOptions = {
enabled: boolean;
target: string;
};
const options = {
enabled: true,
target: "#preview",
} satisfies EmbeddedOptions;
console.log(options);type EmbeddedOptions = {
enabled: boolean;
target: string;
};
const options = {
enabled: true,
target: "#preview",
} satisfies EmbeddedOptions;
console.log(options);import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** 无边框代码块,可嵌入到其他界面中 */
export function CodeHighlightedPlainDemo() {
return (
<DemoProvider>
<div className="grid divide-x divide-lark-line rounded border border-lark-line md:grid-cols-2">
<div className="p-2">
<CodeHighlighted
showLineNumbers
code={`type EmbeddedOptions = {
enabled: boolean;
target: string;
};
const options = {
enabled: true,
target: "#preview",
} satisfies EmbeddedOptions;
console.log(options);`}
lang="typescript"
variant="plain"
/>
</div>
<div className="p-2">
<CodeHighlighted
showCopyButton
code={`type EmbeddedOptions = {
enabled: boolean;
target: string;
};
const options = {
enabled: true,
target: "#preview",
} satisfies EmbeddedOptions;
console.log(options);`}
lang="typescript"
variant="plain"
highlightLines={[6, 7, 8, 9]}
/>
</div>
</div>
</DemoProvider>
);
}完整功能
组合全部功能,获得完整的代码展示体验。
import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
export function CodeExample({ code, language }: Props) {
return (
<ShikiProvider
engine="javascript"
languages={["tsx", "typescript", "bash", "json"]}
>
<CodeHighlighted
code={code}
lang={language}
showCopyButton
/>
</ShikiProvider>
);
}import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** 功能完整示例 */
export function CodeHighlightedFullFeaturedDemo() {
return (
<DemoProvider>
<CodeHighlighted
code={`import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
export function CodeExample({ code, language }: Props) {
return (
<ShikiProvider
engine="javascript"
languages={["tsx", "typescript", "bash", "json"]}
>
<CodeHighlighted
code={code}
lang={language}
showCopyButton
/>
</ShikiProvider>
);
}`}
lang="tsx"
showCopyButton
highlightLines={[6, 7, 8, 9]}
/>
</DemoProvider>
);
}共享 Provider
多个代码块可以共享同一个 ShikiProvider。
Shiki 只加载一次,供所有代码块复用。
const config = { theme: "dark" };npm run build{ "success": true }import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
import { ReactNode } from "react";
/**
* Wrapper component that provides Shiki context for all demos.
* This loads Shiki once and shares it across all CodeHighlighted instances.
*/
function DemoProvider({ children }: { children: ReactNode }) {
return (
<ShikiProvider
engine="javascript"
languages={[
"tsx",
"typescript",
"javascript",
"bash",
"json",
"css",
"html",
]}
>
{children}
</ShikiProvider>
);
}
/** 多个代码块共享同一个 provider */
export function CodeHighlightedSharedProviderDemo() {
return (
<DemoProvider>
<div className="space-y-4">
<CodeHighlighted
code={`const config = { theme: "dark" };`}
lang="typescript"
/>
<CodeHighlighted code={`npm run build`} lang="bash" />
<CodeHighlighted code={`{ "success": true }`} lang="json" />
</div>
</DemoProvider>
);
}主题
CodeHighlighted 使用内置固定主题,以确保所有 Lark 应用中的样式一致:
浅色模式:
github-light深色模式:
vesper
暂不支持自定义主题。这样可以确保应用中所有代码块的视觉一致性。
服务端用法
对于 SSR 框架(Next.js RSC、Astro、Remix),请使用服务端工具在构建时完成高亮。
单次高亮
// Next.js RSC or Astro
import { highlightCode } from "@lark-ui/core/code/server";
export default async function Page() {
const html = await highlightCode(`const x = 1;`, "typescript");
return <pre dangerouslySetInnerHTML={{ __html: html }} />;
}可复用的高亮器
// For multiple highlights, reuse the highlighter
import { createServerHighlighter } from "@lark-ui/core/code/server";
const highlighter = await createServerHighlighter({
languages: ["tsx", "bash", "json"],
});
const html1 = highlighter.highlight(code1, "tsx");
const html2 = highlighter.highlight(code2, "bash");
highlighter.dispose(); // Clean up when done自定义 Hook
使用 useShikiHighlighter 实现自定义方案。
import { useShikiHighlighter } from "@lark-ui/core/code";
function CustomCodeBlock({ code, lang }) {
const { highlight, isLoading, isReady, error } = useShikiHighlighter();
if (error) {
return <div className="text-red-500">Failed to load highlighter</div>;
}
if (isLoading) {
return (
<pre className="animate-pulse">
<code>{code}</code>
</pre>
);
}
const html = highlight(code, lang);
// null means highlighting failed — render plain text
if (html === null) {
return (
<pre>
<code>{code}</code>
</pre>
);
}
return <pre dangerouslySetInnerHTML={{ __html: html }} />;
}国际化
在 provider 层级为所有代码块统一设置按钮文案,也可以按组件单独覆盖。
// Set labels at the provider level for all code blocks
<ShikiProvider
engine="javascript"
languages={["tsx", "bash"]}
labels={{ copy: "Copier", copied: "Copié!" }}
>
<App />
</ShikiProvider>
// Or override at the component level
<CodeHighlighted
code={code}
lang="tsx"
showCopyButton
labels={{ copy: "Copy code", copied: "Done!" }}
/>框架集成
Next.js App Router
// app/providers.tsx
"use client";
import { ShikiProvider } from "@lark-ui/core/code";
export function Providers({ children }) {
return (
<ShikiProvider engine="javascript" languages={["tsx", "bash", "json"]}>
{children}
</ShikiProvider>
);
}
// app/layout.tsx
import { Providers } from "./providers";
export default function RootLayout({ children }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}Astro(静态)
对于静态站点,使用服务端高亮即可实现零客户端 JavaScript。
---
// src/components/CodeBlock.astro
import { highlightCode } from "@lark-ui/core/code/server";
const { code, lang } = Astro.props;
const html = await highlightCode(code, lang);
---
<div class="code-block" set:html={html} />包体积
Shiki 会在首次渲染时懒加载。具体体积取决于你的配置:
| 场景 | 语言 | 引擎 | 懒加载体积 |
|---|---|---|---|
| 最小 | tsx, json | JS | ~75 KB |
| 标准 | tsx, ts, bash, json, css, yaml | JS | ~95 KB |
| 完整 | 15+ 种语言 | WASM | ~250 KB |
未从 @lark-ui/core/code 导入的团队无需承担任何体积成本(0 KB)。
从 Code/CodeBlock 迁移
旧的 Code 和 CodeBlock 组件已废弃,将在 v2.0 中移除。
// Before (deprecated)
import { Code, CodeBlock } from "@lark-ui/core";
<CodeBlock code="const x = 1;" lang="ts" />
// After
import { ShikiProvider, CodeHighlighted } from "@lark-ui/core/code";
// Once at app root
<ShikiProvider engine="javascript" languages={["tsx"]}>
<App />
</ShikiProvider>
// In components
<CodeHighlighted code="const x = 1;" lang="tsx" />API 参考
ShikiProvider 属性
| 属性 | 类型 | 必填 | 描述 |
|---|---|---|---|
engine | ”javascript” | “wasm” | 是 | JS 体积更小(约 50KB),WASM 更准确(约 180KB) |
languages | string[] | 是 | 需要支持的语言(例如 [“tsx”, “bash”]) |
labels | { copy?: string, copied?: string } | 否 | 复制按钮的本地化文案 |
children | ReactNode | 是 | 应用内容 |
CodeHighlighted 属性
| 属性 | 类型 | 必填 | 描述 |
|---|---|---|---|
code | string | 是 | 要展示的源代码 |
lang | string | 是 | 语言标识(必须在 provider 的 languages 中) |
variant | ”default” | “plain” | 否 | 代码块的视觉样式 |
showLineNumbers | boolean | 否 | 显示行号 |
highlightLines | number[] | 否 | 需要突出显示的行(从 1 开始计数) |
showCopyButton | boolean | 否 | 显示复制到剪贴板按钮 |
labels | { copy?: string, copied?: string } | 否 | 为当前实例覆盖 provider 的文案 |
className | string | 否 | 附加的 CSS 类名 |
useShikiHighlighter 返回值
| 属性 | 类型 | 描述 |
|---|---|---|
highlight | (code, lang, options?) => string | null | 返回高亮后的 HTML,若尚未就绪则返回 null |
isLoading | boolean | Shiki 加载期间为 true |
isReady | boolean | 可以安全调用 highlight() 时为 true |
error | Error | null | Shiki 初始化失败时的错误 |