-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* load openapi.json file in web * load openapi.json file in web * load openapi.json file in web * web - fixed coverage * web - removed comments * web - prevent code tok be highlighted twice
- Loading branch information
1 parent
f2da398
commit 08ae816
Showing
24 changed files
with
2,573 additions
and
5,291 deletions.
There are no files selected for viewing
65 changes: 65 additions & 0 deletions
65
agdb_web/components/common/code-block/code-block.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
.header { | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
text-overflow: ellipsis; | ||
white-space: nowrap; | ||
overflow: hidden; | ||
padding: 0.5rem 1rem; | ||
background-color: var(--grey-color-6); | ||
font-size: 0.75rem; | ||
} | ||
.wrapper { | ||
position: relative; | ||
background-color: var(--grey-color-7); | ||
color: var(--grey-color-1); | ||
margin: 0; | ||
overflow-x: auto; | ||
> pre { | ||
padding: 0; | ||
> code { | ||
font-size: 0.8em; | ||
padding: 1rem !important; | ||
} | ||
} | ||
|
||
&:hover .copyButton { | ||
opacity: 1; | ||
} | ||
::selection { | ||
background-color: var(--blue-0) !important; | ||
color: var(--white) !important; | ||
} | ||
} | ||
|
||
.codeBlock { | ||
margin-top: 1.5rem; | ||
border-radius: 0.75rem; | ||
overflow: hidden; | ||
} | ||
|
||
.copyButton { | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
border-radius: 0.375rem; | ||
background-color: var(--grey-color-6); | ||
color: var(--grey-color-3); | ||
cursor: pointer; | ||
transition: | ||
color 0.2s, | ||
opacity 0.2s; | ||
position: absolute; | ||
top: 0.5rem; | ||
right: 0.5rem; | ||
opacity: 0; | ||
padding: 0.375rem; | ||
border: 1px solid var(--grey-color-5); | ||
svg { | ||
width: 1rem; | ||
height: 1rem; | ||
} | ||
&:hover { | ||
color: var(--grey-color-1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { describe, it, expect, vi, beforeEach } from "vitest"; | ||
import { cleanup, render, screen } from "@testing-library/react"; | ||
import { CodeBlock } from "./code-block"; | ||
|
||
const writeText = vi.fn(); | ||
|
||
Object.assign(navigator, { | ||
clipboard: { | ||
writeText, | ||
}, | ||
}); | ||
vi.mock("@/hooks/i18n", () => ({ | ||
useI18n: () => ({ | ||
t: (key: string) => { | ||
if (key === "button.copy-code") return "Copy code"; | ||
return ""; | ||
}, | ||
}), | ||
})); | ||
describe("CodeBlock", () => { | ||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
cleanup(); | ||
}); | ||
it("should render the code block with correct code and language", () => { | ||
const code = `{ | ||
"name": "John Doe", | ||
"age": 30, | ||
"email": " | ||
}`; | ||
render(<CodeBlock code={code} language="json" />); | ||
const text = screen.getByText('"John Doe"'); | ||
expect(text).toBeDefined(); | ||
const copyButton = screen.getByTitle("Copy code"); | ||
expect(copyButton).toBeDefined(); | ||
}); | ||
it("should copy the code to clipboard", () => { | ||
const code = `{ | ||
"name": "John Doe", | ||
"age": 30, | ||
"email": " | ||
}`; | ||
const component = render(<CodeBlock code={code} language="json" />); | ||
const copyButton = component.queryByTestId("copy-code"); | ||
copyButton?.click(); | ||
expect(writeText).toHaveBeenCalledWith(code); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { FC, useRef, useEffect } from "react"; | ||
import styles from "./code-block.module.scss"; | ||
import { CopyIcon } from "nextra/icons"; | ||
import { useI18n } from "@/hooks/i18n"; | ||
import { useHighlight } from "./hooks"; | ||
|
||
export interface CodeBlockProps { | ||
code: string; | ||
language: "json" | "javascript" | "typescript" | "rust" | "python" | "php"; | ||
header?: string; | ||
copy?: boolean; | ||
} | ||
|
||
export const CodeBlock: FC<CodeBlockProps> = ({ | ||
code, | ||
language, | ||
header, | ||
copy = true, | ||
}) => { | ||
const { t } = useI18n(); | ||
|
||
const { highlight, setLanguage } = useHighlight(); | ||
|
||
setLanguage(language); | ||
const codeRef = useRef(null); | ||
|
||
useEffect(() => { | ||
codeRef.current && highlight(codeRef.current); | ||
}, [code, highlight]); | ||
|
||
return ( | ||
<div className={styles.codeBlock}> | ||
{header && <div className={styles.header}>{header}</div>} | ||
<div className={styles.wrapper}> | ||
<pre> | ||
<code ref={codeRef} className={language}> | ||
{code} | ||
</code> | ||
</pre> | ||
{copy && ( | ||
<button | ||
className={styles.copyButton} | ||
onClick={() => navigator.clipboard.writeText(code)} | ||
title={t("button.copy-code")} | ||
data-testid="copy-code" | ||
> | ||
<CopyIcon /> | ||
</button> | ||
)} | ||
</div> | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import { describe, it, expect, vi } from "vitest"; | ||
import { cleanup, renderHook } from "@testing-library/react"; | ||
import { useHighlight } from "./hooks"; | ||
import { render } from "@testing-library/react"; | ||
import { beforeEach } from "node:test"; | ||
|
||
const { languagePackMock } = vi.hoisted(() => ({ | ||
languagePackMock: vi.fn(), | ||
highlightModuleMock: vi.fn(), | ||
})); | ||
|
||
vi.mock("highlight.js/lib/core"); | ||
|
||
vi.mock("highlight.js/lib/languages/json", () => languagePackMock); | ||
vi.mock("highlight.js/lib/languages/rust", () => languagePackMock); | ||
vi.mock("highlight.js/lib/languages/python", () => languagePackMock); | ||
vi.mock("highlight.js/lib/languages/php", () => languagePackMock); | ||
vi.mock("highlight.js/lib/languages/javascript", () => languagePackMock); | ||
vi.mock("highlight.js/lib/languages/typescript", () => languagePackMock); | ||
|
||
describe("useHighlight", () => { | ||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
vi.resetAllMocks(); | ||
vi.resetModules(); | ||
}); | ||
describe("highlight", () => { | ||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
vi.resetModules(); | ||
}); | ||
it("should highlight the code", async () => { | ||
const highlightElementMock = vi.fn(); | ||
const hljs = await import("highlight.js/lib/core"); | ||
hljs.default.highlightElement = highlightElementMock; | ||
|
||
const code = ( | ||
<div>{`{ | ||
"name": "John Doe", | ||
"age": 30, | ||
"email": " | ||
}`}</div> | ||
); | ||
const { container } = render(code); | ||
const { result } = renderHook(() => useHighlight()); | ||
result.current.highlight(container.firstChild as HTMLElement); | ||
expect(highlightElementMock).toHaveBeenCalledWith( | ||
container.firstChild, | ||
); | ||
}); | ||
|
||
it("should not highlight the code again", async () => { | ||
const highlightElementMock = vi.fn(); | ||
const hljs = await import("highlight.js/lib/core"); | ||
hljs.default.highlightElement = highlightElementMock; | ||
|
||
const code = ( | ||
<div>{`{ | ||
"name": "John Doe", | ||
"age": 30, | ||
"email": " | ||
}`}</div> | ||
); | ||
const { container } = render(code); | ||
if (container.firstChild) | ||
(container.firstChild as HTMLElement).dataset.highlighted = | ||
"true"; | ||
const { result } = renderHook(() => useHighlight()); | ||
result.current.highlight(container.firstChild as HTMLElement); | ||
expect(highlightElementMock).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
|
||
describe("setLanguage", () => { | ||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
vi.resetAllMocks(); | ||
vi.resetModules(); | ||
cleanup(); | ||
}); | ||
|
||
it.each([ | ||
["json"], | ||
["rust"], | ||
["python"], | ||
["php"], | ||
["javascript"], | ||
["typescript"], | ||
])("should set the language - %s", async (language) => { | ||
const registerLanguageMock = vi.fn(); | ||
const hljs = await import("highlight.js/lib/core"); | ||
hljs.default.registerLanguage = registerLanguageMock; | ||
const { result } = renderHook(() => useHighlight()); | ||
result.current.setLanguage(language); | ||
expect(registerLanguageMock).toHaveBeenCalledOnce(); | ||
}); | ||
|
||
it("should set the language - empty", async () => { | ||
const registerLanguageMock = vi.fn(); | ||
const hljs = await import("highlight.js/lib/core"); | ||
hljs.default.registerLanguage = registerLanguageMock; | ||
const { result } = renderHook(() => useHighlight()); | ||
result.current.setLanguage(""); | ||
expect(registerLanguageMock).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import hljs from "highlight.js/lib/core"; | ||
|
||
export const useHighlight = () => { | ||
const highlight = (code: HTMLElement) => { | ||
if (!code.dataset.highlighted) { | ||
hljs.highlightElement(code); | ||
} | ||
}; | ||
|
||
const setLanguage = (language: string) => { | ||
switch (language) { | ||
case "json": | ||
hljs.registerLanguage( | ||
"json", | ||
require("highlight.js/lib/languages/json"), | ||
); | ||
break; | ||
case "rust": | ||
hljs.registerLanguage( | ||
"rust", | ||
require("highlight.js/lib/languages/rust"), | ||
); | ||
break; | ||
case "python": | ||
hljs.registerLanguage( | ||
"python", | ||
require("highlight.js/lib/languages/python"), | ||
); | ||
break; | ||
case "php": | ||
hljs.registerLanguage( | ||
"php", | ||
require("highlight.js/lib/languages/php"), | ||
); | ||
break; | ||
case "javascript": | ||
hljs.registerLanguage( | ||
"javascript", | ||
require("highlight.js/lib/languages/javascript"), | ||
); | ||
break; | ||
case "typescript": | ||
hljs.registerLanguage( | ||
"typescript", | ||
require("highlight.js/lib/languages/typescript"), | ||
); | ||
break; | ||
default: | ||
break; | ||
} | ||
}; | ||
|
||
return { highlight, setLanguage }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { CodeBlock } from "./code-block"; | ||
|
||
export default CodeBlock; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { LinkItem } from "./link-item"; | ||
|
||
export default LinkItem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { describe, expect, it, vi } from "vitest"; | ||
import { render, screen } from "@testing-library/react"; | ||
import { LinkItem } from "./link-item"; | ||
|
||
vi.mock("@/hooks/i18n", () => ({ | ||
useI18n: () => ({ | ||
t: (key: string) => { | ||
if (key === "url.about") return "/about"; | ||
if (key === "link.about") return "About"; | ||
return ""; | ||
}, | ||
}), | ||
})); | ||
|
||
describe("LinkItem", () => { | ||
it("should render the link item with correct link and text", () => { | ||
render(<LinkItem i18nKey="about" />); | ||
const link = screen.getByText("About"); | ||
expect(link.getAttribute("href")).toBe("/about"); | ||
}); | ||
}); |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.