refactor(code_highlight): update Code island so it works well on SSR and CSI
+ 114
- 111
@@ -1,10 +1,10 @@
 {
-  "_generatedAtUnix": 1664718648900,
+  "_generatedAtUnix": 1664724678631,
   "_hashAlgorithm": "sha1",
   "_version": 2,
   "islands": {
     "Code": {
-      "hash": "cc253764a3747f0a55ba11d339164711744f832e",
+      "hash": "33a6daff70fa161a3031d82e22db9206e08006bf",
       "pathSource": "./app/islands/Code.tsx",
       "pathBundle": "./public/.islands/Code.bundle.js",
       "pathSourceMap": "./public/.islands/Code.bundle.js.map"

...
@@ -34,7 +34,7 @@
       "pathSourceMap": "./public/.islands/RepositoryCreateForm.bundle.js.map"
     },
     "RepositoryFilesDiffsList": {
-      "hash": "ab4c2ce9ebcbc4e17885f9920da5d36ffb19a232",
+      "hash": "3343a34118a771923801fa256372e534d8599f2c",
       "pathSource": "./app/islands/RepositoryFilesDiffsList.tsx",
       "pathBundle": "./public/.islands/RepositoryFilesDiffsList.bundle.js",
       "pathSourceMap": "./public/.islands/RepositoryFilesDiffsList.bundle.js.map"

app/islands/Code.tsx
@@ -8,8 +8,9 @@ import styled, { css } from "styled-components";
 // app
 import type { AppThemeScheme, WithThemeSchemeProp } from "../types";
 import { NamedColors } from "../utils/style";
+import { escapeHtmlCode, getGitdiffLineStart } from "../utils/shared";
+// app islands
 import { ClientSideRouterEvents } from "./InstantRouterIndicator";
-import { escapeHtmlCode } from "../utils/shared/escapeHtmlCode";
 
 interface CodeProps {
   code: string;

...
@@ -17,60 +18,32 @@ interface CodeProps {
   [x: string]: unknown;
 }
 
-function getLineStartsAt(maybeGitdiff: string): {
-  before: number;
-  after: number;
-} {
-  if (maybeGitdiff == null) {
-    return {
-      before: 0,
-      after: 0,
-    };
-  }
-  const gitdiffLinesRegExp = /@@ -([\d]+),[\d]+ \+[\d]+,([\d]+) @@/i;
-  const matches = gitdiffLinesRegExp.exec(maybeGitdiff);
-  if (matches == null || Array.isArray(matches) === false) {
-    return {
-      before: 0,
-      after: 0,
-    };
-  }
-  const [_, beforeLineNumber, afterLineNumber] = matches;
-  return {
-    before: parseInt(beforeLineNumber, 10) - 1,
-    after: parseInt(afterLineNumber, 10) - 1,
-  };
-}
-
 const Code: ReactIsland<CodeProps & WithThemeSchemeProp> = ({
   code,
   language,
   themeScheme,
   ...props
 }) => {
-  const codeBlockLineStartsAt = useMemo(() => getLineStartsAt(code), [code]);
-  const lineStartAt = codeBlockLineStartsAt.before;
+  const { before: lineStartAt } = useMemo(
+    () => getGitdiffLineStart(code),
+    [code]
+  );
 
   const computeSyntaxHighlightingSSR = useCallback(() => {
-    let innerHtml = {
-      __html: escapeHtmlCode(code),
-    };
-
-    if (
+    const safeLanguage =
       "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
-      );
-    }
-
-    return innerHtml;
+        ? Prism.languages[language]
+        : null;
+    return {
+      __html:
+        safeLanguage != null
+          ? Prism.highlight(code, safeLanguage, language)
+          : escapeHtmlCode(code),
+    };
   }, [code, language]);
 
   const appendLineNumbers = useCallback(

...
@@ -136,12 +109,13 @@ const Code: ReactIsland<CodeProps & WithThemeSchemeProp> = ({
 
   const getHighlightedCodeAsync = useCallback(async () => {
     try {
+      if (code == null || code.trim() === "") {
+        return;
+      }
       const innerHtmlGenerated = await getHighlightedCodeInnerHtml();
       setInnerHtml(innerHtmlGenerated);
-    } catch (err) {
-      // console.error((err as Error).message);
-    }
-  }, [getHighlightedCodeInnerHtml, setInnerHtml]);
+    } catch (_) {}
+  }, [code, getHighlightedCodeInnerHtml, setInnerHtml]);
 
   const onClientSideRouterLoadComplete = useCallback(() => {
     getHighlightedCodeAsync();

app/islands/RepositoryFilesDiffsList.tsx
@@ -30,69 +30,72 @@ const getChunkContent = (chunk: RepositoryFileDiffChunk): string => {
 
 const RepositoryFilesDiffsList: ReactIsland<
   RepositoryFilesDiffsList & WithThemeSchemeProp
-> = ({ commitHash, filesDiffs, orgSlug, repoSlug, themeScheme }) => (
-  <>
-    {getThemedCodeCss(themeScheme)}
-    <Grid.Col fluid>
-      {filesDiffs.map(({ chunks, ...diff }, idx) => (
-        <Card
-          key={[diff.from, diff.to].join(":")}
-          style={{ marginTop: idx > 0 ? 16 : 0, width: "100%" }}
-          themeScheme={themeScheme}
-        >
-          <Grid.Col fluid nowrap>
-            <Grid.Row fluid nowrap>
-              <strong>{diff.from}</strong>
-              <span style={{ marginLeft: 16 }}>{" -> "}</span>
-              <strong style={{ marginLeft: 16 }}>{diff.to}</strong>
-            </Grid.Row>
-            <Grid.Row
-              fluid
-              nowrap
-              alignItems={"center"}
-              style={{ marginTop: 8 }}
-            >
-              <div>
-                <strong>additions:</strong> <span>{diff.additions}</span>
-              </div>
-              <div style={{ marginLeft: 16 }}>
-                <strong>deletions:</strong> <span>{diff.deletions}</span>
-              </div>
-              <div style={{ marginLeft: 16 }}>
-                <a
-                  href={`/${orgSlug}/${repoSlug}/${commitHash}/tree/${diff.to}`}
-                >
-                  View file (current ref)
-                </a>
-                <a
-                  href={`/${orgSlug}/${repoSlug}/${Const.PRIMARY_BRANCH_REF}/tree/${diff.to}`}
-                  style={{ marginLeft: 16 }}
-                >
-                  View file (${Const.PRIMARY_BRANCH_REF})
-                </a>
-              </div>
-            </Grid.Row>
-          </Grid.Col>
-          <Grid.Col fluid style={{ marginTop: 8 }}>
-            {chunks.map((chunk, subIdx) => (
-              <div
-                data-islandid={`${Code.name}$$${idx + 1}${subIdx + 1}`}
-                key={[idx, chunk.content].join(":")}
-                style={{ width: "100%" }}
+> = ({ commitHash, filesDiffs, orgSlug, repoSlug, themeScheme }) => {
+  let codeCounter = 0;
+  return (
+    <>
+      {getThemedCodeCss(themeScheme)}
+      <Grid.Col fluid>
+        {filesDiffs.map(({ chunks, ...diff }, idx) => (
+          <Card
+            key={[diff.from, diff.to].join(":")}
+            style={{ marginTop: idx > 0 ? 16 : 0, width: "100%" }}
+            themeScheme={themeScheme}
+          >
+            <Grid.Col fluid nowrap>
+              <Grid.Row fluid nowrap>
+                <strong>{diff.from}</strong>
+                <span style={{ marginLeft: 16 }}>{" -> "}</span>
+                <strong style={{ marginLeft: 16 }}>{diff.to}</strong>
+              </Grid.Row>
+              <Grid.Row
+                fluid
+                nowrap
+                alignItems={"center"}
+                style={{ marginTop: 8 }}
               >
-                <Code
-                  code={getChunkContent(chunk)}
-                  language={"diff"}
-                  themeScheme={themeScheme}
-                />
-              </div>
-            ))}
-          </Grid.Col>
-        </Card>
-      ))}
-    </Grid.Col>
-  </>
-);
+                <div>
+                  <strong>additions:</strong> <span>{diff.additions}</span>
+                </div>
+                <div style={{ marginLeft: 16 }}>
+                  <strong>deletions:</strong> <span>{diff.deletions}</span>
+                </div>
+                <div style={{ marginLeft: 16 }}>
+                  <a
+                    href={`/${orgSlug}/${repoSlug}/${commitHash}/tree/${diff.to}`}
+                  >
+                    View file (current ref)
+                  </a>
+                  <a
+                    href={`/${orgSlug}/${repoSlug}/${Const.PRIMARY_BRANCH_REF}/tree/${diff.to}`}
+                    style={{ marginLeft: 16 }}
+                  >
+                    View file (${Const.PRIMARY_BRANCH_REF})
+                  </a>
+                </div>
+              </Grid.Row>
+            </Grid.Col>
+            <Grid.Col fluid style={{ marginTop: 8 }}>
+              {chunks.map((chunk, subIdx) => (
+                <div
+                  data-islandid={`${Code.name}$$${codeCounter++}`}
+                  key={[idx, subIdx, chunk.content].join(":")}
+                  style={{ width: "100%" }}
+                >
+                  <Code
+                    code={getChunkContent(chunk)}
+                    language={"diff"}
+                    themeScheme={themeScheme}
+                  />
+                </div>
+              ))}
+            </Grid.Col>
+          </Card>
+        ))}
+      </Grid.Col>
+    </>
+  );
+};
 
 RepositoryFilesDiffsList.displayName = "RepositoryFilesDiffsList";
 export default RepositoryFilesDiffsList;

new file
app/utils/shared/getGitdiffLineStart.ts
@@ -0,0 +1,24 @@
+export default function getGitdiffLineStart(maybeGitdiff: string): {
+  before: number;
+  after: number;
+} {
+  if (maybeGitdiff == null) {
+    return {
+      before: 0,
+      after: 0,
+    };
+  }
+  const gitdiffLinesRegExp = /@@ -([\d]+),[\d]+ \+[\d]+,([\d]+) @@/i;
+  const matches = gitdiffLinesRegExp.exec(maybeGitdiff);
+  if (matches == null || Array.isArray(matches) === false) {
+    return {
+      before: 0,
+      after: 0,
+    };
+  }
+  const [_, beforeLineNumber, afterLineNumber] = matches;
+  return {
+    before: parseInt(beforeLineNumber, 10) - 1,
+    after: parseInt(afterLineNumber, 10) - 1,
+  };
+}

app/utils/shared/index.ts
@@ -1,2 +1,4 @@
 export { default as getFormEntries } from "./getFormEntries";
 export { default as slugify } from "./slugify";
+export { default as getGitdiffLineStart } from "./getGitdiffLineStart";
+export { escapeHtmlCode } from "./escapeHtmlCode";