使用场景
Semi 代码高亮组件基于 Shiki 封装,使用与 VS Code 相同的 TextMate 语法。要高亮的语言由使用方注册,产物中只包含注册过的语法;未注册的语言按纯文本显示。高亮配色默认使用 Shiki 内置的 github-light 与 github-dark 主题,并随 Semi 的亮色、暗色模式自动切换,也可以换成其他主题。
需要展示代码片段时推荐使用 CodeHighlight 组件
代码演示
如何引入
import { CodeHighlight } from '@fibrous/semi-ui-solid';
注册语言与主题
语法与主题文件来自 shiki 包,使用前先在项目中安装 shiki。在应用入口调用一次 CodeHighlight.register,注册之后所有 CodeHighlight 都能使用这些语言。
MarkdownRender、Chat、AIChatDialogue、Sidebar 中的代码块同样生效。
语言以 () => import(...) 的形式传入时,语法文件在首次高亮任一代码块时加载,且会加载全部已注册的语言,而不只是该代码块用到的那一种。可用的语言及其名称、别名见 Shiki 语言列表,主题见 Shiki 主题列表。注册晚于代码块挂载时,已挂载的代码块会重新高亮
import { CodeHighlight } from '@fibrous/semi-ui-solid';
CodeHighlight.register({
languages: [() => import('shiki/langs/javascript.mjs'), () => import('shiki/langs/css.mjs')],
// 可选,替换默认的 github-light 与 github-dark
themes: { light: () => import('shiki/themes/min-light.mjs'), dark: () => import('shiki/themes/nord.mjs') },
});
基本用法
向 code props 传入代码纯文本,并在 language 传入已注册语言的名称或别名
代码
import { CodeHighlight } from '@fibrous/semi-ui-solid';
export default function CodeHighlightDemo() {
return (
<CodeHighlight
language="javascript"
code={`
import * as React from 'react'
const Test = ()=>{
const handleClick = ()=>{
alert("Click")
}
return <div onClick={handleClick}>test</div>
}`}
/>
);
}CSS
代码
import { CodeHighlight } from '@fibrous/semi-ui-solid';
export default function CodeHighlightDemo() {
return (
<CodeHighlight
language="css"
code={`.grid {
.semi-row,
.semi-row-flex {
text-align: center;
.semi-col {
min-height: 30px;
line-height: 30px;
background: var(--semi-color-primary-light-default);
outline: 1px solid var(--semi-color-primary-light-active);
}
}
}
`}
/>
);
}单个代码块使用的语言
只有个别代码块用到的语言,可以通过 languages 传给该代码块,不必全局注册;themes 同样可以只替换该代码块的主题。这两个值请写在组件外部,避免每次渲染都换成新的数组或对象而重新高亮。例如高亮用于编写 GTK 程序前端 UI 的 Vala 语言
代码
import { CodeHighlight } from '@fibrous/semi-ui-solid';
const languages = [() => import('shiki/langs/vala.mjs')];
export default function CodeHighlightDemo() {
return (
<CodeHighlight
languages={languages}
language="vala"
code={`public class ExampleApp : Gtk.Application {
public ExampleApp () {
Object (application_id: "com.example.App");
}
public override void activate () {
var win = new Gtk.ApplicationWindow (this);
var btn = new Gtk.Button.with_label ("Hello World");
btn.clicked.connect (win.close);
win.child = btn;
win.present ();
}
public static int main (string[] args) {
var app = new ExampleApp ();
return app.run (args);
}
}
`}
/>
);
}API
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| code | 代码纯文本,未传时按空字符串处理。code 变化后先显示新文本,高亮完成后再替换。 | string | - |
| language | 语言类型,需已注册或经 languages 传入。 | string | - |
| languages | 该代码块额外使用的 Shiki 语法,加载后其他代码块也可使用。替换为新的数组引用会重新高亮。 | LanguageInput[] | - |
| lineNumber | 是否开启行数显示。 | boolean | true |
| themes | 替换该代码块亮色、暗色模式下的 Shiki 主题。 | CodeHighlightThemes | - |
class、style、ref 与原生属性(如 id、aria-label)落在根元素(div)上,高亮前后根元素保持不变。
静态方法
| 方法 | 说明 | 类型 |
|---|---|---|
| CodeHighlight.register | 注册所有 CodeHighlight 可用的语言,并替换默认主题;可多次调用,语言累加、主题覆盖 | (options: { languages?: LanguageInput[]; themes?: { light?: ThemeInput; dark?: ThemeInput } }) => void |
Accessibility
- 根元素传入
aria-label或aria-labelledby且未传role时,自动带role="group"(通用元素不能被命名);传入的role优先