Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

👩‍💻 Fix SSR styling of code-blocks #480

Merged
merged 8 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/shiny-rocks-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'myst-to-react': patch
---

Fix themeing of code-blocks
90 changes: 59 additions & 31 deletions packages/myst-to-react/src/code.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { NodeRenderer } from '@myst-theme/providers';
import { useThemeSwitcher } from '@myst-theme/providers';
import { LightAsync as SyntaxHighlighter } from 'react-syntax-highlighter';
import light from 'react-syntax-highlighter/dist/esm/styles/hljs/xcode.js';
import dark from 'react-syntax-highlighter/dist/esm/styles/hljs/vs2015.js';
import { DocumentIcon } from '@heroicons/react/24/outline';
import classNames from 'classnames';
import { CopyIcon } from './components/index.js';
import { MyST } from './MyST.js';
import { useMemo, cloneElement } from 'react';

Check warning on line 9 in packages/myst-to-react/src/code.tsx

View workflow job for this annotation

GitHub Actions / lint

'cloneElement' is defined but never used
agoose77 marked this conversation as resolved.
Show resolved Hide resolved
import type { ComponentProps, CSSProperties } from 'react';

type Props = {
value: string;
Expand All @@ -32,8 +33,9 @@
}
}

type HighlightPropsType = ComponentProps<typeof SyntaxHighlighter>;

export function CodeBlock(props: Props) {
const { isLight } = useThemeSwitcher();
agoose77 marked this conversation as resolved.
Show resolved Hide resolved
const {
value,
lang,
Expand All @@ -49,6 +51,59 @@
border,
} = props;
const highlightLines = new Set(emphasizeLines);
const highlighterProps: Omit<HighlightPropsType, 'children'> = {
language: normalizeLanguage(lang),
startingLineNumber,
showLineNumbers,
wrapLines: true,
lineNumberContainerStyle: {
// This stops page content shifts
display: 'inline-block',
float: 'left',
minWidth: '1.25em',
paddingRight: '1em',
textAlign: 'right',
userSelect: 'none',
borderLeft: '4px solid transparent',
},
lineProps: (line: number | boolean) => {
if (typeof line === 'boolean') return {};
return highlightLines.has(line)
? ({
'data-line-number': `${line}`,
'data-highlight': 'true',
} as any)
: ({ 'data-line-number': `${line}` } as any);
},
customStyle: {
padding: '0.8rem',
// Take over display in order to style via classes
display: null,
},
};

const darkStyle = useMemo<HighlightPropsType['style']>(() => {
const style = dark as CSSProperties;
return style as any;
}, []);
const darkComponent = (
<SyntaxHighlighter {...highlighterProps} className="hidden dark:block" style={darkStyle}>
{value}
</SyntaxHighlighter>
);

const lightStyle = useMemo<HighlightPropsType['style']>(() => {
return {
...(light as CSSProperties),
hljs: { ...light.hljs, background: 'transparent' },
} as any;
}, []);
const lightComponent = (
<SyntaxHighlighter {...highlighterProps} className="block dark:hidden" style={lightStyle}>
{value}
</SyntaxHighlighter>
);

return (
<div
id={identifier}
Expand All @@ -71,35 +126,8 @@
</div>
</div>
)}
<SyntaxHighlighter
language={normalizeLanguage(lang)}
startingLineNumber={startingLineNumber}
showLineNumbers={showLineNumbers}
style={isLight ? { ...light, hljs: { ...light.hljs, background: 'transparent' } } : dark}
wrapLines
lineNumberContainerStyle={{
// This stops page content shifts
display: 'inline-block',
float: 'left',
minWidth: '1.25em',
paddingRight: '1em',
textAlign: 'right',
userSelect: 'none',
borderLeft: '4px solid transparent',
}}
lineProps={(line) => {
if (typeof line === 'boolean') return {};
return highlightLines.has(line)
? ({
'data-line-number': `${line}`,
'data-highlight': 'true',
} as any)
: ({ 'data-line-number': `${line}` } as any);
}}
customStyle={{ padding: '0.8rem' }}
>
{value}
</SyntaxHighlighter>
{darkComponent}
{lightComponent}
{showCopy && (
<CopyIcon
text={value}
Expand Down
Loading