Skip to content

Commit

Permalink
feat(code): code highlight and cache
Browse files Browse the repository at this point in the history
  • Loading branch information
GaoNeng-wWw committed Oct 16, 2024
1 parent 1e3007f commit cfe1b89
Show file tree
Hide file tree
Showing 13 changed files with 857 additions and 9 deletions.
5 changes: 3 additions & 2 deletions doc/docs/components/show/code/basic-usage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import React from 'react';
import {Code, CodeFile} from '@qwqui/core';

export default function App(){
const codes = Array.from({length:100}).fill('console.log("aaa");').join('\n');
return (
<Code>
<CodeFile name="index.ts" code="// index.ts" />
<CodeFile name="file.ts" code="// file.ts" />
<CodeFile name="index.ts" code="// Comment" language="javascript" />
<CodeFile name="file.ts" code={codes} language="javascript" />
</Code>
)
}
3 changes: 3 additions & 0 deletions packages/components/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@
},
"devDependencies": {
"@qwqui/tools": "workspace:^"
},
"dependencies": {
"shiki": "^1.22.0"
}
}
40 changes: 40 additions & 0 deletions packages/components/code/src/code-body.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useContext, useEffect, useMemo, useState } from "react"
import { createHighlighter } from 'shiki';
import { CodeContext, CodeContextType } from "./code-context"
import style from './styles/code-body.module.scss';
import './styles/hack.css';
import {darkTheme} from './dark-theme'

export const CodeBody = () => {
const {activeCode,codeFiles, cache} = useContext<CodeContextType>(CodeContext);
const [code, setCode] = useState('');
const [codeLanguage, setCodeLanguage] = useState('');
useEffect(()=>{
const [codeFile] = codeFiles.filter((file) => file.name === activeCode);
if (!codeFile){
return;
}
setCode(codeFile.code);
setCodeLanguage(codeFile.language);
}, [activeCode, codeFiles]);
const [html, setHTML] = useState('');
useMemo(async ()=>{
if (cache.has(code)) {
return cache.get(code);
}
const highLighter = await createHighlighter({
langs: [codeLanguage],
themes: []
});
await highLighter.loadTheme(darkTheme as unknown as Record<string, string>);
const html = highLighter.codeToHtml(code, {
lang: codeLanguage,
theme: 'dark-theme'
})
setHTML(html);
cache.set(code, html);
}, [code, codeLanguage, cache]);
return (
<div className={style.root} dangerouslySetInnerHTML={{__html: html}}></div>
)
}
3 changes: 2 additions & 1 deletion packages/components/code/src/code-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ export type CodeContextType = {
prevX: number;
setPrevX: React.Dispatch<React.SetStateAction<number>>;
prevWidth: number;
setPrevWidth: React.Dispatch<React.SetStateAction<number>>
setPrevWidth: React.Dispatch<React.SetStateAction<number>>;
cache: Map<string, string>;
}
6 changes: 3 additions & 3 deletions packages/components/code/src/code-file.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ const hasCode = (name: string, code: string, codeFiles: CodeFileProps[]) => {

export const CodeFile = factory<CodeFileProps>((props) => {
const {codeFiles, setCodeFiles} = useContext<CodeContextType>(CodeContext);
const {name, code} = props;
const {name, code, language} = props;
useEffect(()=>{
if (!hasCode(name, code, codeFiles)){
setCodeFiles([
...codeFiles,
{name, code}
{name, code, language}
])
}
}, [name, code, codeFiles, setCodeFiles])
}, [name, code, codeFiles, language, setCodeFiles])
return (
<></>
)
Expand Down
6 changes: 5 additions & 1 deletion packages/components/code/src/code.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CodeFileProps, CodeWrapper } from './code.types';
import { CodeHeader } from './code-header';
import { useEffect, useState } from 'react';
import style from './styles/code-wrapper.module.scss';
import { CodeBody } from './code-body';

export const Code = factory<CodeWrapper>((props)=>{
const [codeFiles, setCodeFiles] = useState<CodeFileProps[]>([]);
Expand All @@ -12,6 +13,7 @@ export const Code = factory<CodeWrapper>((props)=>{
const [width, setWidth] = useState(72);
const [prevX,setPrevX] = useState();
const [prevWidth, setPrevWidth] = useState();
const cache = new Map();
useEffect(()=>{
if (codeFiles[0]){
setActiveCode(codeFiles[0].name);
Expand All @@ -30,10 +32,12 @@ export const Code = factory<CodeWrapper>((props)=>{
prevX,
setPrevX,
prevWidth,
setPrevWidth
setPrevWidth,
cache
}}>
<div className={style.root}>
<CodeHeader />
<CodeBody />
{props.children}
</div>
</CodeContext.Provider>
Expand Down
3 changes: 2 additions & 1 deletion packages/components/code/src/code.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ export interface CodeWrapper {
showTrafficLight: boolean;
logo: React.ReactNode;
isColored: boolean;
children?: React.ReactDOM
children?: React.ReactNode
}

export interface CodeFileProps {
name: string;
code: string;
icon?: React.ReactNode;
language: string;
}

export interface CodeHeaderProps {
Expand Down
Loading

0 comments on commit cfe1b89

Please sign in to comment.