Refactor highlight
This commit is contained in:
parent
6e61ff7194
commit
4b24ce85e0
|
|
@ -0,0 +1,27 @@
|
|||
.italic {
|
||||
font-style: italic;
|
||||
color: var(--italicColor, #AFAFAF);
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.quote {
|
||||
color: var(--quoteColor, #D4E5FF);
|
||||
}
|
||||
|
||||
.codeBlock {
|
||||
font-family: monospace;
|
||||
background: var(--codeBg, #49483e);
|
||||
padding: 0.5em;
|
||||
display: block;
|
||||
border-radius: var(--radius, 4px);
|
||||
}
|
||||
|
||||
.inlineCode {
|
||||
font-family: monospace;
|
||||
background: var(--codeBg, #49483e);
|
||||
padding: 0.1em 0.3em;
|
||||
border-radius: 0.2em;
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import styles from './assets/highlight.module.css';
|
||||
|
||||
export const highlight = (message: string, keepMarkup = true): string => {
|
||||
let resultHTML = '';
|
||||
const tokenRegex = /(\*\*?|"|```|`)/g;
|
||||
const stack: string[] = [];
|
||||
let inCodeBlock = false;
|
||||
let lastIndex = 0;
|
||||
let match: RegExpExecArray | null;
|
||||
|
||||
while ((match = tokenRegex.exec(message)) !== null) {
|
||||
resultHTML += message.slice(lastIndex, match.index);
|
||||
lastIndex = tokenRegex.lastIndex;
|
||||
|
||||
const token = match[0];
|
||||
const isClose = stack.at(-1) === token;
|
||||
const keepToken = keepMarkup || token === '"';
|
||||
|
||||
if (inCodeBlock) {
|
||||
if (token === '```' && isClose) {
|
||||
inCodeBlock = false;
|
||||
stack.pop();
|
||||
resultHTML += `${keepToken ? token : ''}</span>`;
|
||||
} else {
|
||||
resultHTML += token;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isClose) {
|
||||
stack.pop();
|
||||
resultHTML += `${keepToken ? token : ''}</span>`;
|
||||
} else if (token === '*') {
|
||||
stack.push(token);
|
||||
resultHTML += `<span class="${styles.italic}">${keepToken ? token : ''}`;
|
||||
} else if (token === '**') {
|
||||
stack.push(token);
|
||||
resultHTML += `<span class="${styles.bold}">${keepToken ? token : ''}`;
|
||||
} else if (token === '"') {
|
||||
stack.push(token);
|
||||
resultHTML += `<span class="${styles.quote}">"`;
|
||||
} else if (token === '```') {
|
||||
stack.push(token);
|
||||
inCodeBlock = true;
|
||||
resultHTML += `<span class="${styles.codeBlock}">`;
|
||||
} else if (token === '`') {
|
||||
stack.push(token);
|
||||
resultHTML += `<span class="${styles.inlineCode}">`;
|
||||
}
|
||||
}
|
||||
|
||||
resultHTML += message.slice(lastIndex);
|
||||
|
||||
resultHTML += '</span>'.repeat(stack.length);
|
||||
|
||||
return resultHTML;
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { useInputState } from "@common/hooks/useInputState";
|
||||
import { highlight } from "@common/highlight";
|
||||
import { Sidebar } from "./sidebar";
|
||||
import { useAppState, type ChatMessage } from "../contexts/state";
|
||||
import styles from '../assets/chat-sidebar.module.css';
|
||||
import { useState, useRef, useEffect, useMemo, useCallback } from "preact/hooks";
|
||||
import LLM from "../utils/llm";
|
||||
import { highlight } from "../utils/highlight";
|
||||
import Prompt from "../utils/prompt";
|
||||
import { Tools } from "../utils/tools";
|
||||
import clsx from "clsx";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { ContentEditable } from "@common/components/ContentEditable";
|
||||
import { highlight } from "@common/highlight";
|
||||
import { useAppState, type Tab } from "../contexts/state";
|
||||
import styles from '../assets/editor.module.css';
|
||||
import { highlight } from "../utils/highlight";
|
||||
import { useMemo } from "preact/hooks";
|
||||
import { CharacterEditor } from "./character-editor";
|
||||
import { LocationEditor } from "./location-editor";
|
||||
|
|
|
|||
|
|
@ -1,63 +0,0 @@
|
|||
export const highlight = (message: string, keepMarkup = true): string => {
|
||||
let resultHTML = '';
|
||||
const replaceRegex = /(\*\*?|"|```|`)/ig;
|
||||
const splitToken = '___SPLIT_AWOORWA___';
|
||||
|
||||
const preparedMessage = message.replace(replaceRegex, `${splitToken}$1${splitToken}`);
|
||||
const parts = preparedMessage.split(splitToken);
|
||||
|
||||
const stack: string[] = [];
|
||||
let inCodeBlock = false;
|
||||
|
||||
for (const part of parts) {
|
||||
const isClose = stack.at(-1) === part;
|
||||
const keepPart = keepMarkup || part === '"';
|
||||
|
||||
if (inCodeBlock) {
|
||||
if (part === '```' && isClose) {
|
||||
inCodeBlock = false;
|
||||
stack.pop();
|
||||
resultHTML += `${keepPart ? part : ''}</span>`;
|
||||
} else {
|
||||
resultHTML += part;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isClose) {
|
||||
stack.pop();
|
||||
if (part === '*' || part === '**' || part === '"' || part === '`' || part === '```') {
|
||||
resultHTML += `${keepPart ? part : ''}</span>`;
|
||||
}
|
||||
} else {
|
||||
if (part === '*') {
|
||||
stack.push(part);
|
||||
resultHTML += `<span style="font-style:italic;color:var(--italicColor)">${keepPart ? part : ''}`;
|
||||
} else if (part === '**') {
|
||||
stack.push(part);
|
||||
resultHTML += `<span style="font-weight:bold">${keepPart ? part : ''}`;
|
||||
} else if (part === '"') {
|
||||
stack.push(part);
|
||||
resultHTML += `<span style="color:var(--quoteColor)">"`;
|
||||
} else if (part === '```') {
|
||||
stack.push(part);
|
||||
inCodeBlock = true;
|
||||
resultHTML += `<span style="font-family:monospace;background:var(--codeBg);padding:0.5em;display:block;border-radius:var(--radius)">`;
|
||||
} else if (part === '`') {
|
||||
stack.push(part);
|
||||
resultHTML += `<span style="font-family:monospace;background:var(--codeBg);padding:0.1em 0.3em;border-radius:0.2em">`;
|
||||
} else {
|
||||
resultHTML += part;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (stack.length) {
|
||||
const part = stack.pop();
|
||||
if (part === '*' || part === '**' || part === '"' || part === '`' || part === '```') {
|
||||
resultHTML += `</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
return resultHTML;
|
||||
}
|
||||
Loading…
Reference in New Issue