Skip to content

Commit

Permalink
refactor: sync wrap states in localstorage
Browse files Browse the repository at this point in the history
  • Loading branch information
OzakIOne committed Sep 28, 2023
1 parent 2251be0 commit 86ea394
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export default function CodeBlockString({
ref={wordWrap.codeBlockRef}
className={clsx(className, styles.codeBlock, 'thin-scrollbar')}>
<code
style={wordWrap.codeStyle}
className={clsx(
styles.codeBlockLines,
showLineNumbers && styles.codeBlockLinesWithNumbering,
Expand Down
38 changes: 21 additions & 17 deletions packages/docusaurus-theme-common/src/hooks/useCodeWordWrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type {RefObject} from 'react';
import type {CSSProperties, RefObject} from 'react';
import {useState, useCallback, useEffect, useRef} from 'react';
import {useStorageSlot} from '../index';
import {useMutationObserver} from './useMutationObserver';
Expand Down Expand Up @@ -53,30 +53,34 @@ function useTabBecameVisibleCallback(
);
}

function useCodeWrapState() {
const [value, storageSlot] = useStorageSlot('docusaurus.code.wordWrap');

const toggle = useCallback(() => {
const newValue = value === 'true' ? 'false' : 'true';
storageSlot.set(newValue);
}, [value, storageSlot]);

return [value === 'true', toggle] as const;
}

export function useCodeWordWrap(): {
readonly codeBlockRef: RefObject<HTMLPreElement>;
readonly isEnabled: boolean;
readonly isCodeScrollable: boolean;
readonly toggle: () => void;
readonly codeStyle: CSSProperties;
} {
const [value, storageSlot] = useStorageSlot('docusaurus.code.wordWrap');
const [isEnabled, toggleWrap] = useCodeWrapState();
const [isCodeScrollable, setIsCodeScrollable] = useState<boolean>(false);
const codeBlockRef = useRef<HTMLPreElement>(null);
const codeStyle: CSSProperties = isEnabled
? {whiteSpace: 'pre-wrap', overflowWrap: 'anywhere'}
: {};

const toggle = useCallback(() => {
const codeElement = codeBlockRef.current!.querySelector('code')!;

if (value === 'true') {
codeElement.removeAttribute('style');
} else {
codeElement.style.whiteSpace = 'pre-wrap';
// When code wrap is enabled, we want to avoid a scrollbar in any case
// Ensure that very very long words/strings/tokens still wrap
codeElement.style.overflowWrap = 'anywhere';
}

storageSlot.set(value === 'true' ? 'false' : 'true');
}, [codeBlockRef, value, storageSlot]);
toggleWrap();
}, [toggleWrap]);

const updateCodeIsScrollable = useCallback(() => {
const {scrollWidth, clientWidth} = codeBlockRef.current!;
Expand All @@ -90,7 +94,7 @@ export function useCodeWordWrap(): {

useEffect(() => {
updateCodeIsScrollable();
}, [value, updateCodeIsScrollable]);
}, [isEnabled, updateCodeIsScrollable]);

useEffect(() => {
window.addEventListener('resize', updateCodeIsScrollable, {
Expand All @@ -102,5 +106,5 @@ export function useCodeWordWrap(): {
};
}, [updateCodeIsScrollable]);

return {codeBlockRef, isEnabled: value === 'true', isCodeScrollable, toggle};
return {codeBlockRef, isEnabled, isCodeScrollable, toggle, codeStyle};
}

0 comments on commit 86ea394

Please sign in to comment.