Workaround Docusaurus prism highlighting hydration bug (#1519)
Summary: Pull Request resolved: https://github.com/facebook/yoga/pull/1519 See https://github.com/facebook/docusaurus/issues/9629 We use prism to render the code for the inline editor. Prism renders colors to style directly, and the color chosen is dependent on a setting that may not be available at SSR time. This adds an SSR-specific representation of the code, missing some of the nuances in token colorization (similar to https://github.com/facebook/docusaurus/pull/7373). This adds a little bit of jank compared to perfect SSR, but fixes cases where the mode is incorrect, and is a lot less jank then the more generic solution used by theme-live-codeblock of keeping the rendering of the opposite color until rehydration. Preview: https://yoga-website-next-git-fork-nickgerleman-exp-2f8171-fbopensource.vercel.app/ Reviewed By: yungsters Differential Revision: D52163722 fbshipit-source-id: 312dc52134f0084d40f78147190151700ee10ff7
This commit is contained in:
committed by
Facebook GitHub Bot
parent
3f6f04cb92
commit
2caa8ac8cb
@@ -9,12 +9,16 @@ html[data-theme='light'] {
|
||||
--yg-color-preview-background: var(--ifm-color-primary-lighter);
|
||||
--yg-color-playground-background: var(--ifm-color-gray-200);
|
||||
--yg-color-editor-border: var(--ifm-color-gray-400);
|
||||
--yg-color-editor-fallback-bg: rgb(246, 248, 250);
|
||||
--yg-color-editor-fallback-text: rgb(0, 0, 159);
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
--yg-color-preview-background: var(--ifm-color-primary-dark);
|
||||
--yg-color-playground-background: var(--ifm-color-background);
|
||||
--yg-color-editor-border: var(--ifm-color-gray-800);
|
||||
--yg-color-editor-fallback-bg: rgb(40, 44, 52);
|
||||
--yg-color-editor-fallback-text: rgb(209, 154, 102);
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
@@ -47,8 +51,8 @@ html[data-theme='dark'] {
|
||||
|
||||
.editorToolbar {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
top: var(--ifm-pre-padding);
|
||||
right: var(--ifm-pre-padding);
|
||||
}
|
||||
|
||||
.playgroundEditor {
|
||||
@@ -62,6 +66,12 @@ html[data-theme='dark'] {
|
||||
box-shadow: var(--ifm-global-shadow-lw);
|
||||
min-height: 100%;
|
||||
border-radius: 0;
|
||||
padding: var(--ifm-pre-padding) !important;
|
||||
}
|
||||
|
||||
.liveEditorFallback {
|
||||
background-color: var(--yg-color-editor-fallback-bg);
|
||||
color: var(--yg-color-editor-fallback-text);
|
||||
}
|
||||
|
||||
.previewColumn {
|
||||
|
@@ -27,6 +27,7 @@ import type {FlexStyle} from './FlexStyle';
|
||||
import type {StyleNode} from './YogaViewer';
|
||||
|
||||
import styles from './Playground.module.css';
|
||||
import useIsBrowser from '@docusaurus/useIsBrowser';
|
||||
|
||||
export type Props = Readonly<{
|
||||
code: string;
|
||||
@@ -37,6 +38,7 @@ export type Props = Readonly<{
|
||||
export default function Playground({code, height, autoFocus}: Props) {
|
||||
const prismTheme = usePrismTheme();
|
||||
const editorScrollRef = useRef<HTMLDivElement>(null);
|
||||
const isBrowser = useIsBrowser();
|
||||
|
||||
const [liveCode, setLiveCode] = useState(code);
|
||||
const [hasCodeChanged, setHasCodeChanged] = useState(false);
|
||||
@@ -72,6 +74,11 @@ export default function Playground({code, height, autoFocus}: Props) {
|
||||
? ({'--yg-playground-height': height} as React.CSSProperties)
|
||||
: undefined;
|
||||
|
||||
const handleCodeChange = useCallback((code: string) => {
|
||||
setHasCodeChanged(true);
|
||||
setLiveCode(code);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<LiveProvider
|
||||
code={liveCode}
|
||||
@@ -86,13 +93,15 @@ export default function Playground({code, height, autoFocus}: Props) {
|
||||
className={styles.editorToolbar}
|
||||
style={{paddingRight: scrollbarWidth + 'px'}}
|
||||
/>
|
||||
<LiveEditor
|
||||
className={clsx(styles.playgroundEditor)}
|
||||
onChange={useCallback((code: string) => {
|
||||
setHasCodeChanged(true);
|
||||
setLiveCode(code);
|
||||
}, [])}
|
||||
/>
|
||||
|
||||
{isBrowser ? (
|
||||
<LiveEditor
|
||||
className={clsx(styles.playgroundEditor)}
|
||||
onChange={handleCodeChange}
|
||||
/>
|
||||
) : (
|
||||
<LiveEditorFallback code={liveCode} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={clsx(styles.previewColumn)}>
|
||||
@@ -105,6 +114,21 @@ export default function Playground({code, height, autoFocus}: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a non-editable approximation of the LiveEditor result, without
|
||||
* relying on prism rendering, for use during SSR.
|
||||
* See https://github.com/facebook/docusaurus/issues/9629
|
||||
*/
|
||||
function LiveEditorFallback({code}: Readonly<{code: string}>) {
|
||||
return (
|
||||
<div className={clsx(styles.playgroundEditor)}>
|
||||
<pre className={clsx('prism-code', styles.liveEditorFallback)}>
|
||||
{code}
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
type RootLiveNodeProps = Readonly<{
|
||||
children: React.ReactNode;
|
||||
config?: {useWebDefaults?: boolean};
|
||||
|
Reference in New Issue
Block a user