Skip to content

Commit

Permalink
fix: Add langStyle prop, separate from style, update README (#8)
Browse files Browse the repository at this point in the history
fix: Add langStyle prop, separate from style, update README
  • Loading branch information
AVGVSTVS96 authored Jan 30, 2025
1 parent 11eac95 commit ec59b10
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 28 deletions.
7 changes: 7 additions & 0 deletions package/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# react-shiki

## 0.2.3

### Patch Changes

- Add `langStyle` prop, separate from code block's `style`
Update README

## 0.2.2

### Patch Changes
Expand Down
18 changes: 11 additions & 7 deletions package/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
> This package is still a work in progress, fully functional but not
> extensively tested.
Performant server and client side syntax highlighting component + hook
Performant client side syntax highlighting component + hook
for react using [Shiki](https://shiki.matsu.io/)

[See the demo page with highlighted code blocks showcasing several Shiki themes!](https://react-shiki.vercel.app/)
Expand All @@ -17,7 +17,7 @@ for react using [Shiki](https://shiki.matsu.io/)
- [Usage](#usage)
- [`react-markdown`](#react-markdown)
- [Custom themes](#custom-themes)
- [Client-side highlighting](#client-side-highlighting)
- [Performance](#performance)
- [Throttling real-time highlighting](#throttling-real-time-highlighting)
- [Streaming and LLM chat UI](#streaming-and-llm-chat-ui)
<!--toc:end-->
Expand Down Expand Up @@ -74,6 +74,8 @@ function CodeBlock() {
}
```

The `ShikiHighlighter` component will follow a similar API to `react-syntax-highlighter`, but uses Shiki and is optimized for performant sequential highlighting. As of now, not all of `react-syntax-highlighter` functionality is supported, but the goal of this component is to eventually act as a drop in replacement for `react-syntax-highlighter`.

The component accepts several props in addition to language and theme:

- `showLanguage: boolean` - Shows the language name in the top right corner of
Expand All @@ -84,13 +86,15 @@ The component accepts several props in addition to language and theme:
- `delay: number` - Delay between highlights in milliseconds, useful for throttling
rapid highlighting on the client
- `className: string` - Class name to be passed to the component
- `style: object` - Style object to be passed to the component
- `style: object` - Inline style object to be passed to the component
- `langStyle: object` - Inline style object to be passed to the language label

```tsx
function Houston() {
return (
<ShikiHighlighter
language="jsx"
className="code-block"
theme="houston"
showLanguage={false}
addDefaultStyles={true}
Expand All @@ -105,7 +109,7 @@ function Houston() {
}
```

**react-shiki** exports `isInlineCode` to check if a code block is inline:
`react-shiki` exports `isInlineCode` to check if a code block is inline:

```tsx
const isInline: boolean | undefined = node ? isInlineCode(node) : undefined;
Expand Down Expand Up @@ -173,9 +177,9 @@ import tokyoNight from '@styles/tokyo-night.mjs';
</ShikiHighlighter>;
```

## Client-side highlighting
## Performance

react-shiki supports performance-optimized highlighting on the client.
`react-shiki` supports performance-optimized highlighting on the client.

### Throttling real-time highlighting

Expand All @@ -190,7 +194,7 @@ const highlightedCode = useShikiHighlighter(code, language, theme, {

### Streaming and LLM chat UI

react-shiki can be used to highlight streamed code from LLM responses in real-time.
`react-shiki` can be used to highlight streamed code from LLM responses in real-time.

I use it for an
LLM chatbot UI, it renders markdown and highlights code in memoized chat messages.
Expand Down
2 changes: 1 addition & 1 deletion package/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "react-shiki",
"description": "Syntax highlighter component for react using shiki",
"version": "0.2.2",
"version": "0.2.3",
"license": "MIT",
"author": {
"name": "Bassim Shahidy",
Expand Down
8 changes: 7 additions & 1 deletion package/src/ShikiHighlighter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ export interface ShikiHighlighterProps extends HighlighterOptions {
*/
style?: React.CSSProperties;

/**
* Add custom inline styles to the language label
*/
langStyle?: React.CSSProperties;

/**
* Add custom CSS class names to the generated code block
*/
Expand Down Expand Up @@ -85,6 +90,7 @@ export const ShikiHighlighter = ({
delay,
addDefaultStyles = true,
style,
langStyle,
className,
showLanguage = true,
children: code,
Expand All @@ -102,7 +108,7 @@ export const ShikiHighlighter = ({
style={style}
>
{showLanguage && language ? (
<span className="languageLabel" style={style}>
<span className="languageLabel" style={langStyle}>
{language}
</span>
) : null}
Expand Down
38 changes: 19 additions & 19 deletions package/src/useShiki.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ import type {
import { removeTabIndexFromPre } from '@/utils';


/************************************
** Singleton highlighter instance **
************************************/
/**
* Singleton highlighter instance
*/
let highlighterPromise: Promise<Highlighter> | null = null;


/***********************************************************
** Creates or returns the singleton highlighter instance **
***********************************************************/
/**
* Creates or returns the singleton highlighter instance
*/
const makeHighlighter = async (theme: Theme): Promise<Highlighter> => {
if (!highlighterPromise) {
highlighterPromise = createHighlighter({
Expand All @@ -41,9 +41,9 @@ const makeHighlighter = async (theme: Theme): Promise<Highlighter> => {
};


/************************************************************
** Loads a theme dynamically if it hasn't been loaded yet **
************************************************************/
/**
* Loads a theme dynamically if it hasn't been loaded yet
*/
const loadTheme = async (
highlighter: Highlighter,
theme: Theme
Expand All @@ -59,9 +59,9 @@ const loadTheme = async (
};


/******************************************************************************
** Loads a language dynamically, falling back to plaintext if not available ** **
******************************************************************************/
/**
* Loads a language dynamically, falling back to plaintext if not available
*/
const loadLanguage = async (
highlighter: Highlighter,
lang: Language
Expand All @@ -80,9 +80,9 @@ const loadLanguage = async (
};


/*******************************************************************************
** Throttles highlighting operations to prevent overwhelming the highlighter ** **
*******************************************************************************/
/**
* Optionally throttles rapid sequential highlighting operations to conserve resources
*/
const throttleHighlighting = (
performHighlight: () => Promise<void>,
timeoutControl: React.MutableRefObject<TimeoutState>,
Expand All @@ -99,10 +99,10 @@ const throttleHighlighting = (
};


/************************************************************************
** A React hook that provides syntax highlighting using Shiki. Uses a **
** singleton highlighter instance and supports throttled updates. **
*************************************************************************/
/**
* A React hook that provides syntax highlighting using Shiki. Uses a
* singleton highlighter instance and supports optional throttled highlights
*/
export const useShikiHighlighter = (
code: string,
lang: Language,
Expand Down

0 comments on commit ec59b10

Please sign in to comment.