Files
paseo/packages/app/src/styles/syntax-token-styles.ts
T
Mohamed BoudraandGitHub f6afe0d864 feat(app): syntax highlighting and copy button for chat code blocks (#1062)
Adds Lezer-based highlighting to fenced code blocks in assistant messages,
with a hover/tap copy button. Colors move into the theme as
`theme.colors.syntax`, so the chat blocks, file preview, and diff viewer
share one StyleSheet path — token color updates flow through the Unistyles
native ShadowRegistry with no React re-renders on the chat hot path.
2026-05-17 16:01:08 +08:00

41 lines
2.0 KiB
TypeScript

import { StyleSheet } from "react-native-unistyles";
// Per-token color styles for syntax-highlighted code. Each value reads a
// theme path so the Unistyles Babel plugin tracks the dependency and updates
// native style values on theme changes — no React re-render of consumers.
// Used by message code blocks (hot path), file preview, and the diff viewer.
export const syntaxTokenStyles = StyleSheet.create((theme) => ({
base: { color: theme.colors.foreground },
keyword: { color: theme.colors.syntax.keyword },
comment: { color: theme.colors.syntax.comment },
string: { color: theme.colors.syntax.string },
number: { color: theme.colors.syntax.number },
literal: { color: theme.colors.syntax.literal },
function: { color: theme.colors.syntax.function },
definition: { color: theme.colors.syntax.definition },
class: { color: theme.colors.syntax.class },
type: { color: theme.colors.syntax.type },
tag: { color: theme.colors.syntax.tag },
attribute: { color: theme.colors.syntax.attribute },
property: { color: theme.colors.syntax.property },
variable: { color: theme.colors.syntax.variable },
operator: { color: theme.colors.syntax.operator },
punctuation: { color: theme.colors.syntax.punctuation },
regexp: { color: theme.colors.syntax.regexp },
escape: { color: theme.colors.syntax.escape },
meta: { color: theme.colors.syntax.meta },
heading: { color: theme.colors.syntax.heading },
link: { color: theme.colors.syntax.link },
}));
type SyntaxTokenStyleValue = (typeof syntaxTokenStyles)["base"];
// Accepts a plain string so diff tokens (server-typed `string | null`) and
// @getpaseo/highlight tokens (typed `HighlightStyle | null`) share one path.
// Unknown styles fall back to the base color.
export function syntaxTokenStyleFor(style: string | null | undefined): SyntaxTokenStyleValue {
if (!style) return syntaxTokenStyles.base;
const indexed = syntaxTokenStyles as unknown as Record<string, SyntaxTokenStyleValue>;
return indexed[style] ?? syntaxTokenStyles.base;
}