Skip to content

Commit 9ef300e

Browse files
committed
Theme: Replace the default CodeBlock component
This modified version allows injecting snippet contents dynamically based on their database key, and will inject an error if it failed to load. Only snippets with the 'source" key will be considered and the rest is left unchanged, so that the change is non-disruptive.
1 parent bb6d1fc commit 9ef300e

2 files changed

Lines changed: 53 additions & 0 deletions

File tree

src/theme/CodeBlock/index.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/// <reference types="react" />
2+
import type { Props } from '@theme/CodeBlock';
3+
export default function CodeBlock({ children: rawChildren, ...props }: Props): JSX.Element;

src/theme/CodeBlock/index.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React, {isValidElement} from 'react';
2+
import useIsBrowser from '@docusaurus/useIsBrowser';
3+
import ElementContent from '@theme/CodeBlock/Content/Element';
4+
import StringContent from '@theme/CodeBlock/Content/String';
5+
/**
6+
* Best attempt to make the children a plain string so it is copyable. If there
7+
* are react elements, we will not be able to copy the content, and it will
8+
* return `children` as-is; otherwise, it concatenates the string children
9+
* together.
10+
*/
11+
function maybeStringifyChildren(children) {
12+
if (React.Children.toArray(children).some((el) => isValidElement(el))) {
13+
return children;
14+
}
15+
// The children is now guaranteed to be one/more plain strings
16+
return Array.isArray(children) ? children.join('') : children;
17+
}
18+
19+
// This is only needed to automatically check for dead links (when building the docs)
20+
const GITHUB_BASE_URL = "https://github.com/evo-lua/evo-luvi/blob/main/Tests/Examples/";
21+
22+
export default function CodeBlock({children: rawChildren, ...props}) {
23+
// The Prism theme on SSR is always the default theme but the site theme can
24+
// be in a different mode. React hydration doesn't update DOM styles that come
25+
// from SSR. Hence force a re-render after mounting to apply the current
26+
// relevant styles.
27+
const isBrowser = useIsBrowser();
28+
const children = maybeStringifyChildren(rawChildren);
29+
const CodeBlockComp =
30+
typeof children === 'string' ? StringContent : ElementContent;
31+
32+
// This should be added to the final HTML page's DOM, so that the link checker script can pick it up
33+
const snippetSourceURL = GITHUB_BASE_URL + props.source;
34+
const optionalSourceLink = props.source ? <><a className="optional-snippet-source" href={snippetSourceURL}>{snippetSourceURL}</a></> : "";
35+
36+
let sourceCode = "Loading snippet...";
37+
if (props.source) {
38+
sourceCode = require("/static/examples-autogenerated.json")[props.source] ?? "[[ERROR: Failed to load snippet " + props.source + "\nReason: No such entry exists in the autogenerated snippet database\n\nPlease report this problem!]]" ;
39+
} else {
40+
sourceCode = children; // It's a regular code snippet that doesn't need fetching from the DB
41+
}
42+
return (
43+
<>
44+
<CodeBlockComp key={String(isBrowser)} {...props}>
45+
{sourceCode}
46+
</CodeBlockComp>
47+
{optionalSourceLink}
48+
</>
49+
);
50+
}

0 commit comments

Comments
 (0)