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 { useInputState } from "@common/hooks/useInputState";
|
||||||
|
import { highlight } from "@common/highlight";
|
||||||
import { Sidebar } from "./sidebar";
|
import { Sidebar } from "./sidebar";
|
||||||
import { useAppState, type ChatMessage } from "../contexts/state";
|
import { useAppState, type ChatMessage } from "../contexts/state";
|
||||||
import styles from '../assets/chat-sidebar.module.css';
|
import styles from '../assets/chat-sidebar.module.css';
|
||||||
import { useState, useRef, useEffect, useMemo, useCallback } from "preact/hooks";
|
import { useState, useRef, useEffect, useMemo, useCallback } from "preact/hooks";
|
||||||
import LLM from "../utils/llm";
|
import LLM from "../utils/llm";
|
||||||
import { highlight } from "../utils/highlight";
|
|
||||||
import Prompt from "../utils/prompt";
|
import Prompt from "../utils/prompt";
|
||||||
import { Tools } from "../utils/tools";
|
import { Tools } from "../utils/tools";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { ContentEditable } from "@common/components/ContentEditable";
|
import { ContentEditable } from "@common/components/ContentEditable";
|
||||||
|
import { highlight } from "@common/highlight";
|
||||||
import { useAppState, type Tab } from "../contexts/state";
|
import { useAppState, type Tab } from "../contexts/state";
|
||||||
import styles from '../assets/editor.module.css';
|
import styles from '../assets/editor.module.css';
|
||||||
import { highlight } from "../utils/highlight";
|
|
||||||
import { useMemo } from "preact/hooks";
|
import { useMemo } from "preact/hooks";
|
||||||
import { CharacterEditor } from "./character-editor";
|
import { CharacterEditor } from "./character-editor";
|
||||||
import { LocationEditor } from "./location-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