@svelte-dev/pretty-code

一个漂亮的 Svelte MDsveX 代码高亮显示插件

@svelte-dev/pretty-code 是一个由 rehype-pretty-codeshikiji 提供支持的 MDsveX 高亮插件。这个语法高亮器为 Markdown 或 MDsveX 提供了漂亮的代码块。它只适用于 块代码(不适用于 内联代码)。

编辑器级高亮

享受 VS Code 语法高亮引擎的准确性和粒度, 以及其主题生态系统的流行 —— 使用任何你想要的 VS Code 主题!

demo.tsx
import { useFloating, offset } from '@floating-ui/react';
 
interface Props {
  open: boolean;
  onOpenChange(open: boolean): void;
}
 
export function App({ open, onOpenChange }: Props) {
  const { refs, floatingStyles } = useFloating({
    open,
    onOpenChange,
    placement: 'left',
    middleware: [offset(10)]
  });
 
  return (
    <Container>
      <div ref={refs.setReference} />
      {open && <div ref={refs.setFloating} style={floatingStyles} />}
    </Container>
  );
}

行号和行高亮

将注意力引向特定的代码行。

import { useFloating } from '@floating-ui/react';
 
function MyComponent() {
  const { refs, floatingStyles } = useFloating();
 
  return (
    <>
      <div ref={refs.setReference} />
      <div ref={refs.setFloating} style={floatingStyles} />
    </>
  );
}
Caption

单词高亮

将注意力引向特定的单词或字符序列。

import { useFloating } from '@floating-ui/react';
 
function MyComponent() {
  const { refs, floatingStyles } = useFloating();
 
  return (
    <>
      <div ref={refs.setReference} />
      <div ref={refs.setFloating} style={floatingStyles} />
    </>
  );
}

ANSI 高亮

  vite v5.0.0 dev server running at:
 
  > Local: http://localhost:3000/
  > Network: use `--host` to expose
 
  ready in 125ms.
 
8:38:02 PM [vite] hmr update /src/App.jsx

安装

通过终端进行安装:

npm add @svelte-dev/pretty-code

此包仅支持 ESM,并且当前支持 shikiji ^0.7.0 || ^0.8.0

使用

以下在服务器和客户端上都可以工作。

unified@11 被用作依赖项。

import { defineMDSveXConfig as defineConfig } from 'mdsvex';
import { createHighlighter } from '@svelte-dev/pretty-code';
 
const config = defineConfig({
  extensions: ['.svelte.md', '.md', '.svx'],
 
  highlight: {
    highlighter: createHighlighter({
      // keepBackground: false,
      theme: {
        dark: 'solarized-dark',
        light: 'solarized-light'
      }
    })
  }
});
 
export default config;

选项

interface Options {
  grid?: boolean;
  theme?: Theme | Record<string, Theme>;
  keepBackground?: boolean;
  defaultLang?: string;
  tokensMap?: Record<string, string>;
  transformers?: ShikijiTransformer[];
  filterMetaString?(str: string): string;
  getHighlighter?(options: BundledHighlighterOptions): Promise<Highlighter>;
  onVisitLine?(element: LineElement): void;
  onVisitHighlightedLine?(element: LineElement): void;
  onVisitHighlightedChars?(element: CharsElement, id: string | undefined): void;
  onVisitTitle?(element: Element): void;
  onVisitCaption?(element: Element): void;
}

grid

默认情况下存在一个网格样式,允许行高亮跨越水平滚动的代码块的整个宽度。

如果需要,你可以禁用此设置:

const options = {
  grid: false
};

theme

默认主题是 github-dark-dimmed。Shikiji 有一堆 预打包的主题, 可以指定为一个简单的字符串:

const options = {
  theme: 'one-dark-pro'
};

你也可以通过传递主题 JSON 来使用你自己的主题:

const options = {
  theme: JSON.parse(
    fs.readFileSync(new URL('./themes/moonlight-ii.json', import.meta.url), 'utf-8')
  )
};

keepBackground

要应用自定义背景,而不是从主题继承背景:

const options = {
  keepBackground: false
};

defaultLang

你可以指定一个默认语言:

const options = {
  defaultLang: 'plaintext'
};

transformers

Transformers 是一种 Shikiji-native 的方式来操作代码块的 hAST 树,并进一步扩展此插件的行为。shikiji-transformers 包提供了一些有用的 transformers。

import { transformerNotationDiff } from 'shikiji-transformers';
 
const options = {
  transformers: [transformerNotationDiff()]
};

Meta Strings

通过顶部代码块围栏上的元字符串配置代码块。

如果你的库也解析代码块的元字符串,它可能会 引起冲突rehype-pretty-code。此选项允许你在库开始解析之前过滤掉元字符串的一部分。

const options = {
  filterMetaString: (string) => string.replace(/filename="[^"]*"/, '')
};

高亮行

{} 内放置一个数字范围。

\```js {1-3,4}
 
\```

<span> 接收一个 data-highlighted-line 属性以通过 CSS 进行样式化。

通过 Id 分组高亮行

{} 后面放置一个 # 后面的 id。这允许你根据他们的 id 以不同的颜色或样式对行进行着色。

\```js {1,2}#a {3,4}#b
 
\```

<span> 接收一个 data-highlighted-line-id="<id>" 属性 以通过 CSS 进行样式化。

高亮字符

你可以使用 /

\```js /carrot/
 
\```

或者 " 作为分隔符:

\```js "carrot"
\```

也可以高亮不同的字符段:

\```js /carrot/ /apple/
 
\```

字符 <span> 接收一个 data-highlighted-chars 属性以通过 CSS 进行样式化。

要只高亮 carrot 的第三到第五个实例,可以在最后一个 / 后面放置一个数字范围。

\```js /carrot/3-5
 
\```

只高亮 carrot 的第三到第五个实例和 apple 的任何实例。

\```js /carrot/3-5 /apple/
 
\```

通过 Id 分组高亮字符

在字符后面放置一个 # 后面的 id。这允许你根据他们的 id 以不同的颜色对字符进行着色。

\```js /age/#v /name/#v /setAge/#s /setName/#s /50/#i /'Taylor'/#i
const [age, setAge] = useState(50);
const [name, setName] = useState('Taylor');
\```
const [age, setAge] = useState(50);
const [name, setName] = useState('Taylor');

字符 <span> 接收一个 data-chars-id="<id>" 属性以通过 CSS 进行样式化。

标题

在你的代码块中添加一个文件标题,文本在双引号 ("") 内:

\```js title="..."
 
\```

标题

在你的代码块下方添加一个标题,文本在双引号 ("") 内:

\```js caption="..."
 
\```

行号

可以使用 CSS 计数器添加行号。

code {
  counter-reset: line;
}
 
code > [data-line]::before {
  counter-increment: line;
  content: counter(line);
 
  /* 其他样式 */
  display: inline-block;
  width: 1rem;
  margin-right: 2rem;
  text-align: right;
  color: gray;
}
 
code[data-line-numbers-max-digits='2'] > [data-line]::before {
  width: 2rem;
}
 
code[data-line-numbers-max-digits='3'] > [data-line]::before {
  width: 3rem;
}

如果你想条件显示它们,使用 showLineNumbers

\```js showLineNumbers
 
\```

<code> 将具有属性 data-line-numbersdata-line-numbers-max-digits="n"

如果你想从特定的数字开始行号,使用 showLineNumbers{number}

\```js showLineNumbers{number}
 
\```

多主题(深色和浅色模式)

将你的主题传递给 theme,其中键代表 颜色模式:

const options = {
  theme: {
    dark: 'github-dark-dimmed',
    light: 'github-light'
  }
};

现在,使用以下 CSS 来显示变量颜色 —— 如果在主题名称中找到空格,那么基于对象的 CSS 变量键将可用 (更多信息):

code[data-theme*=' '],
code[data-theme*=' '] span {
  color: var(--shiki-light);
  background-color: var(--shiki-light-bg);
}
 
@media (prefers-color-scheme: dark) {
  code[data-theme*=' '],
  code[data-theme*=' '] span {
    color: var(--shiki-dark);
    background-color: var(--shiki-dark-bg);
  }
}

<code><pre> 元素将具有数据属性 data-theme="...themes",列出每个主题值以空格分隔:

<code data-theme="github-dark-dimmed github-light"></code>

访问者钩子

要自定义 HTML 输出,你可以使用访问者回调钩子直接操作 hAST 元素

const options = {
  onVisitLine(element) {
    console.log('Visited line');
  },
  onVisitHighlightedLine(element) {
    console.log('Visited highlighted line');
  },
  onVisitHighlightedChars(element) {
    console.log('Visited highlighted chars');
  },
  onVisitTitle(element) {
    console.log('Visited title');
  },
  onVisitCaption(element) {
    console.log('Visited caption');
  }
};

自定义高亮器

要完全配置高亮器,使用 getHighlighter 选项。如果你想配置其他 Shikiji 选项,如 langs,这将很有帮助。

import { getHighlighter } from 'shikiji';
 
const options = {
  getHighlighter: (options) =>
    getHighlighter({
      ...options,
      langs: ['plaintext', async () => JSON.parse(await readFile('my-grammar.json', 'utf-8'))]
    })
};

赞助

维护者: Willin Wang

如果您对本项目感兴趣,可以通过以下方式支持我:

License

Apache-2.0