mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-30 22:22:02 +02:00
Text selection and syntax highlighting to markdown previews
https://feedback.yaak.app/p/enable-text-selection-in-the-info-section
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import type { CSSProperties } from 'react';
|
||||
import ReactMarkdown, { type Components } from 'react-markdown';
|
||||
import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import { ErrorBoundary } from './ErrorBoundary';
|
||||
import { Prose } from './Prose';
|
||||
@@ -22,6 +24,57 @@ export function Markdown({ children, className }: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
const prismTheme = {
|
||||
'pre[class*="language-"]': {
|
||||
// Needs to be here, so the lib doesn't add its own
|
||||
},
|
||||
|
||||
// Syntax tokens
|
||||
comment: { color: 'var(--textSubtle)' },
|
||||
prolog: { color: 'var(--textSubtle)' },
|
||||
doctype: { color: 'var(--textSubtle)' },
|
||||
cdata: { color: 'var(--textSubtle)' },
|
||||
|
||||
punctuation: { color: 'var(--textSubtle)' },
|
||||
|
||||
property: { color: 'var(--primary)' },
|
||||
'attr-name': { color: 'var(--primary)' },
|
||||
|
||||
string: { color: 'var(--notice)' },
|
||||
char: { color: 'var(--notice)' },
|
||||
|
||||
number: { color: 'var(--info)' },
|
||||
constant: { color: 'var(--info)' },
|
||||
symbol: { color: 'var(--info)' },
|
||||
|
||||
boolean: { color: 'var(--warning)' },
|
||||
'attr-value': { color: 'var(--warning)' },
|
||||
|
||||
variable: { color: 'var(--success)' },
|
||||
|
||||
tag: { color: 'var(--info)' },
|
||||
operator: { color: 'var(--danger)' },
|
||||
keyword: { color: 'var(--danger)' },
|
||||
function: { color: 'var(--success)' },
|
||||
'class-name': { color: 'var(--primary)' },
|
||||
builtin: { color: 'var(--danger)' },
|
||||
selector: { color: 'var(--danger)' },
|
||||
inserted: { color: 'var(--success)' },
|
||||
deleted: { color: 'var(--danger)' },
|
||||
regex: { color: 'var(--warning)' },
|
||||
|
||||
important: { color: 'var(--danger)', fontWeight: 'bold' },
|
||||
italic: { fontStyle: 'italic' },
|
||||
bold: { fontWeight: 'bold' },
|
||||
entity: { cursor: 'help' },
|
||||
};
|
||||
|
||||
const lineStyle: CSSProperties = {
|
||||
paddingRight: '1.5em',
|
||||
paddingLeft: '0',
|
||||
opacity: 0.5,
|
||||
};
|
||||
|
||||
const markdownComponents: Partial<Components> = {
|
||||
// Ensure links open in external browser by adding target="_blank"
|
||||
a: ({ href, children, ...rest }) => {
|
||||
@@ -34,4 +87,27 @@ const markdownComponents: Partial<Components> = {
|
||||
</a>
|
||||
);
|
||||
},
|
||||
code(props) {
|
||||
const { children, className, ref, ...extraProps } = props;
|
||||
delete extraProps.node;
|
||||
|
||||
const match = /language-(\w+)/.exec(className || '');
|
||||
return match ? (
|
||||
<SyntaxHighlighter
|
||||
{...extraProps}
|
||||
CodeTag="code"
|
||||
showLineNumbers
|
||||
PreTag="div"
|
||||
lineNumberStyle={lineStyle}
|
||||
language={match[1]}
|
||||
style={prismTheme}
|
||||
>
|
||||
{String(children).replace(/\n$/, '')}
|
||||
</SyntaxHighlighter>
|
||||
) : (
|
||||
<code {...extraProps} ref={ref} className={className}>
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -47,7 +47,7 @@ export function MarkdownEditor({
|
||||
<p className="text-text-subtlest">No description</p>
|
||||
) : (
|
||||
<div className="overflow-y-auto max-h-full [&_*]:cursor-auto [&_*]:select-auto">
|
||||
<Markdown className="max-w-lg">{defaultValue}</Markdown>
|
||||
<Markdown className="max-w-lg select-auto cursor-auto">{defaultValue}</Markdown>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
@@ -118,9 +118,10 @@
|
||||
@apply bg-surface-highlight text-text !important;
|
||||
@apply px-4 py-3 rounded-md;
|
||||
@apply overflow-auto whitespace-pre;
|
||||
@apply text-editor font-mono;
|
||||
|
||||
code {
|
||||
@apply text-xs font-normal;
|
||||
@apply font-normal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user