Skip to content

Commit

Permalink
🐛 fix(hightlight): Fix prompt highlight
Browse files Browse the repository at this point in the history
  • Loading branch information
canisminor1990 committed Sep 4, 2023
1 parent fa10967 commit a2698af
Show file tree
Hide file tree
Showing 7 changed files with 282 additions and 99 deletions.
175 changes: 103 additions & 72 deletions javascript/main.js

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,15 @@
"remark-cli": "^11",
"semantic-release": "^21",
"semver": "^7.5.4",
"shiki-es": "^0.14",
"styled-components": "^6",
"stylelint": "^15.10",
"swr": "^2",
"terser": "^5",
"typescript": "^5",
"vite": "^4",
"zustand": "^4"
"zustand": "^4.4.1",
"zustand-utils": "^1.3.1"
},
"peerDependencies": {
"antd": ">=5",
Expand Down
2 changes: 1 addition & 1 deletion src/modules/PromptHighlight/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { SyntaxHighlighter } from '@lobehub/ui';
import { useScroll, useSize } from 'ahooks';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';

import { useExternalTextareaObserver } from '@/hooks/useExternalTextareaObserver';

import SyntaxHighlighter from './SyntaxHighlighter';
import grammar from './prompt.tmLanguage.json';
import { themeConfig } from './promptTheme';
import { useStyles } from './style';
Expand Down
49 changes: 49 additions & 0 deletions src/modules/PromptHighlight/SyntaxHighlighter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Icon } from '@lobehub/ui';
import { useThemeMode } from 'antd-style';
import { Loader2 } from 'lucide-react';
import { memo, useEffect } from 'react';
import { Center } from 'react-layout-kit';
import { type HighlighterOptions } from 'shiki-es';

import { useStyles } from './style';
import { useHighlight } from './useHighlight';

export interface SyntaxHighlighterProps {
children: string;
language: string;
options?: HighlighterOptions;
}

const SyntaxHighlighter = memo<SyntaxHighlighterProps>(({ children, language, options }) => {
const { styles } = useStyles();
const { isDarkMode } = useThemeMode();
const [codeToHtml, isLoading] = useHighlight((s) => [s.codeToHtml, !s.highlighter]);

useEffect(() => {
useHighlight.getState().initHighlighter(options);
}, [options]);

return (
<>
{isLoading ? (
<code>{children}</code>
) : (
<div
className={styles.shiki}
dangerouslySetInnerHTML={{
__html: codeToHtml(children, language, isDarkMode) || '',
}}
/>
)}

{isLoading && (
<Center className={styles.loading} gap={8} horizontal>
<Icon icon={Loader2} spin />
Highlighting...
</Center>
)}
</>
);
});

export default SyntaxHighlighter;
82 changes: 61 additions & 21 deletions src/modules/PromptHighlight/style.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,63 @@
import { createStyles } from 'antd-style';

export const useStyles = createStyles(({ css, token }) => ({
container: css`
pointer-events: none;
position: absolute;
overflow-x: hidden;
overflow-y: auto;
padding: 8px;
pre {
font-family: ${token.fontFamilyCode} !important;
font-size: 13px;
line-height: 18.2px;
color: ${token.colorSuccess};
word-wrap: break-word;
white-space: pre-wrap;
}
`,
}));
export const useStyles = createStyles(({ css, token, cx, stylish, prefixCls }) => {
const prefix = `${prefixCls}-highlighter`;
return {
container: css`
pointer-events: none;
position: absolute;
overflow-x: hidden;
overflow-y: auto;
padding: 8px;
pre {
font-family: ${token.fontFamilyCode} !important;
font-size: 13px !important;
line-height: 1.5 !important;
color: ${token.colorSuccess};
text-overflow: ellipsis !important;
word-wrap: break-word;
white-space: pre-wrap;
vertical-align: bottom !important;
}
`,
loading: cx(
stylish.blur,
css`
position: absolute;
z-index: 10;
top: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
height: 34px;
padding: 0 8px;
font-family: ${token.fontFamilyCode};
color: ${token.colorTextTertiary};
border-radius: ${token.borderRadius};
`,
),
shiki: cx(
`${prefix}-shiki`,
css`
margin: 0;
padding: 0;
.shiki {
overflow-x: auto;
margin: 0;
padding: 0;
background: none !important;
}
`,
),
};
});
60 changes: 60 additions & 0 deletions src/modules/PromptHighlight/useHighlight.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { type Highlighter, type HighlighterOptions, getHighlighter } from 'shiki-es';
import { shallow } from 'zustand/shallow';
import { createWithEqualityFn } from 'zustand/traditional';

export const languageMap = [] as const;

/**
* @title 代码高亮的存储对象
*/
interface Store {
/**
* @title Convert code to HTML string
* @param text - The code text
* @param language - The language of the code
* @param isDarkMode - Whether it's in dark mode or not
* @returns HTML string
*/
codeToHtml: (text: string, language: string, isDarkMode: boolean) => string;
/**
* @title Highlighter object
*/
highlighter?: Highlighter;
/**
* @title Initialize the highlighter object
* @returns Initialization promise object
*/
initHighlighter: (options?: HighlighterOptions) => Promise<void>;
}

export const useHighlight = createWithEqualityFn<Store>(
(set, get) => ({
codeToHtml: (text, language, isDarkMode) => {
const { highlighter } = get();

if (!highlighter) return '';

try {
return highlighter?.codeToHtml(text, {
lang: language,
theme: isDarkMode ? 'dark' : 'light',
});
} catch {
return text;
}
},
highlighter: undefined,

initHighlighter: async(options) => {
if (!get().highlighter) {
const highlighter = await getHighlighter({
langs: options?.langs,
themes: options?.themes,
});

set({ highlighter });
}
},
}),
shallow,
);
9 changes: 5 additions & 4 deletions src/pages/Content/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,13 @@ export const useStyles = createStyles(
overflow-y: auto;
padding: 8px;
padding: 8px !important;
font-family: ${token.fontFamilyCode};
font-size: 13px;
text-overflow: ellipsis;
vertical-align: bottom;
font-size: 13px !important;
line-height: 1.5 !important;
word-wrap: break-word !important;
white-space: pre-wrap !important;
transition:
all 0.3s,
Expand Down

0 comments on commit a2698af

Please sign in to comment.