refactor(code_highlight): update Code island so it works well on SSR and CSI@@ -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"
@@ -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();
@@ -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;
@@ -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,
+ };
+}
@@ -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";