From 633c96d619008f701a54148c214c1e151cfd8919 Mon Sep 17 00:00:00 2001 From: keyan Date: Wed, 20 Dec 2023 18:16:34 -0600 Subject: [PATCH] handle hash urls with 'view more' --- components/table-of-contents.js | 4 ++++ components/text.js | 20 +++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/components/table-of-contents.js b/components/table-of-contents.js index c150bf07..956dadaf 100644 --- a/components/table-of-contents.js +++ b/components/table-of-contents.js @@ -6,8 +6,10 @@ import { fromMarkdown } from 'mdast-util-from-markdown' import { visit } from 'unist-util-visit' import { toString } from 'mdast-util-to-string' import GithubSlugger from 'github-slugger' +import { useRouter } from 'next/router' export default function Toc ({ text }) { + const router = useRouter() if (!text || text.length === 0) { return null } @@ -42,6 +44,8 @@ export default function Toc ({ text }) { marginLeft: `${(v.depth - 1) * 5}px` }} href={`#${v.slug}`} key={v.slug} + // nextjs router doesn't emit hashChangeStart events + onClick={() => router.events.emit('hashChangeStart', `#${v.slug}`, { shallow: true })} >{v.heading} ) diff --git a/components/text.js b/components/text.js index 5bae23ca..e49ec298 100644 --- a/components/text.js +++ b/components/text.js @@ -17,6 +17,7 @@ import { IMGPROXY_URL_REGEXP } from '../lib/url' import reactStringReplace from 'react-string-replace' import { rehypeInlineCodeProperty } from '../lib/md' import { Button } from 'react-bootstrap' +import { useRouter } from 'next/router' export function SearchText ({ text }) { return ( @@ -33,9 +34,23 @@ export function SearchText ({ text }) { // this is one of the slowest components to render export default memo(function Text ({ nofollow, imgproxyUrls, children, tab, ...outerProps }) { const [overflowing, setOverflowing] = useState(false) + const router = useRouter() const [show, setShow] = useState(false) const containerRef = useRef(null) + useEffect(() => { + setShow(router.asPath.includes('#')) + const handleRouteChange = (url, { shallow }) => { + setShow(url.includes('#')) + } + + router.events.on('hashChangeStart', handleRouteChange) + + return () => { + router.events.off('hashChangeStart', handleRouteChange) + } + }, [router]) + useEffect(() => { const container = containerRef.current if (!container || overflowing) return @@ -58,14 +73,13 @@ export default memo(function Text ({ nofollow, imgproxyUrls, children, tab, ...o } }, [containerRef.current, setOverflowing]) - // all the reactStringReplace calls are to facilitate search highlighting - const slugger = useRef(new GithubSlugger()) + const slugger = new GithubSlugger() const Heading = useCallback(({ children, node, ...props }) => { const [copied, setCopied] = useState(false) const { noFragments, topLevel } = outerProps const id = useMemo(() => - noFragments ? undefined : slugger?.current?.slug(toString(node).replace(/[^\w\-\s]+/gi, '')), [node, noFragments, slugger]) + noFragments ? undefined : slugger?.slug(toString(node).replace(/[^\w\-\s]+/gi, '')), [node, noFragments, slugger]) const h = useMemo(() => { if (topLevel) { return node?.TagName