@@ -50,43 +51,104 @@ const Code: ReactIsland<CodeProps & WithThemeSchemeProp> = ({
const codeBlockLineStartsAt = useMemo(() => getLineStartsAt(code), [code]);
const lineStartAt = codeBlockLineStartsAt.before;
- const computeSyntaxHighlighting = useCallback(() => {
- const innerHtml = {
- __html:
- typeof window === "undefined" &&
- Prism != null &&
- typeof Prism !== "undefined" &&
- "languages" in Prism &&
- Prism.languages != null &&
- typeof Prism.languages === "object" &&
- language in Prism.languages &&
- Prism.languages[language] != null
- ? Prism.highlight(code, Prism.languages[language], language)
- : escapeHtmlCode(code),
+ const computeSyntaxHighlightingSSR = useCallback(() => {
+ let innerHtml = {
+ __html: escapeHtmlCode(code),
};
- const linesCount = innerHtml.__html.split("\n").length;
-
- innerHtml.__html += `\n<span aria-hidden="true" class="line-numbers-rows">`;
- for (let i = linesCount; i > 0; i--) {
- const lineNumber = lineStartAt + (linesCount - i + 1);
- innerHtml.__html += `<a id="l-${lineNumber}" href="#l-${lineNumber}" data-line-number="${lineNumber}"></a>`;
+ if (
+ "languages" in Prism &&
+ Prism.languages != null &&
+ typeof Prism.languages === "object" &&
+ language in Prism.languages &&
+ Prism.languages[language] != null
+ ) {
+ innerHtml.__html = Prism.highlight(
+ code,
+ Prism.languages[language],
+ language
+ );
}
- innerHtml.__html += `</span>`;
return innerHtml;
- }, [code, language, lineStartAt]);
+ }, [code, language]);
+
+ const appendLineNumbers = useCallback(
+ (inHtml: {
+ __html: string;
+ }): {
+ __html: string;
+ } => {
+ const copyInnerHtml = { __html: inHtml.__html };
+ const linesCount = copyInnerHtml.__html.split("\n").length;
+ copyInnerHtml.__html += `\n<span aria-hidden="true" class="line-numbers-rows">`;
+ for (let i = linesCount; i > 0; i--) {
+ const lineNumber = lineStartAt + (linesCount - i + 1);
+ copyInnerHtml.__html += `<a id="l-${lineNumber}" href="#l-${lineNumber}" data-line-number="${lineNumber}"></a>`;
+ }
+ copyInnerHtml.__html += `</span>`;
+ return copyInnerHtml;
+ },
+ [lineStartAt]
+ );
const [innerHtml, setInnerHtml] = useState<{ __html: string }>(
- computeSyntaxHighlighting()
+ appendLineNumbers(computeSyntaxHighlightingSSR())
);
+ const getHighlightedCodeInnerHtml = useCallback(async (): Promise<{
+ __html: string;
+ }> => {
+ let inHtml;
+ if (typeof window === "undefined") {
+ inHtml = computeSyntaxHighlightingSSR();
+ } else {
+ const { protocol, hostname, port } = new URL(window.location.href);
+ const res = await fetch(
+ `${protocol}//${hostname}:${port}/api/syntax/highlight/html`,
+ {
+ method: "POST",
+ headers: {
+ Accept: "application/json",
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ code,
+ language,
+ theme_scheme: themeScheme,
+ }),
+ }
+ );
+ const jsonRes = await res.json();
+ inHtml = {
+ __html: jsonRes.html,
+ };
+ }
+ inHtml = appendLineNumbers(inHtml);
+ return inHtml;
+ }, [
+ code,
+ language,
+ themeScheme,
+ appendLineNumbers,
+ computeSyntaxHighlightingSSR,
+ ]);
+
+ const getHighlightedCodeAsync = useCallback(async () => {
+ try {
+ const innerHtmlGenerated = await getHighlightedCodeInnerHtml();
+ setInnerHtml(innerHtmlGenerated);
+ } catch (err) {
+ // console.error((err as Error).message);
+ }
+ }, [getHighlightedCodeInnerHtml, setInnerHtml]);
+
const onClientSideRouterLoadComplete = useCallback(() => {
- setInnerHtml(computeSyntaxHighlighting());
- }, [computeSyntaxHighlighting, setInnerHtml]);
+ getHighlightedCodeAsync();
+ }, [getHighlightedCodeAsync]);
useEffect(() => {
- setInnerHtml(computeSyntaxHighlighting());
+ onClientSideRouterLoadComplete();
document.addEventListener(
ClientSideRouterEvents.NAVIGATED,
onClientSideRouterLoadComplete