From 5634f4d9030c9c2799ca2f806012f7cad67a54b5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 30 Aug 2025 19:44:21 +0000
Subject: [PATCH 1/3] Initial plan
From 6b365e898e42f7d6f71cb1643a473017c63c4920 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 30 Aug 2025 19:57:10 +0000
Subject: [PATCH 2/3] Add syntax highlighting to CodeBlock component using
react-syntax-highlighter
Co-authored-by: msaroufim <3282513+msaroufim@users.noreply.github.com>
---
frontend/package-lock.json | 287 ++++++++++++++++++
frontend/package.json | 2 +
.../components/codeblock/CodeBlock.test.tsx | 54 ++++
.../src/components/codeblock/CodeBlock.tsx | 38 ++-
.../pages/leaderboard/Leaderboard.test.tsx | 9 +-
.../src/pages/leaderboard/Leaderboard.tsx | 2 +-
6 files changed, 376 insertions(+), 16 deletions(-)
create mode 100644 frontend/src/components/codeblock/CodeBlock.test.tsx
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 45d02a5..5f10118 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -12,6 +12,7 @@
"@emotion/styled": "^11.14.1",
"@mui/icons-material": "^7.2.0",
"@mui/material": "^7.2.0",
+ "@types/react-syntax-highlighter": "^15.5.13",
"dayjs": "^1.11.13",
"imurmurhash": "^0.1.4",
"react": "^19.1.0",
@@ -19,6 +20,7 @@
"react-icons": "^5.5.0",
"react-markdown": "^10.1.0",
"react-router-dom": "^7.6.2",
+ "react-syntax-highlighter": "^15.6.6",
"rehype-raw": "^7.0.0",
"zustand": "^5.0.7"
},
@@ -2031,6 +2033,15 @@
"@types/react": "^19.0.0"
}
},
+ "node_modules/@types/react-syntax-highlighter": {
+ "version": "15.5.13",
+ "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz",
+ "integrity": "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/react-transition-group": {
"version": "4.4.12",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
@@ -3299,6 +3310,19 @@
"reusify": "^1.0.4"
}
},
+ "node_modules/fault": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz",
+ "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==",
+ "license": "MIT",
+ "dependencies": {
+ "format": "^0.2.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -3363,6 +3387,14 @@
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
"dev": true
},
+ "node_modules/format": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
+ "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==",
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -3580,6 +3612,21 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/highlight.js": {
+ "version": "10.7.3",
+ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
+ "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/highlightjs-vue": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz",
+ "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==",
+ "license": "CC0-1.0"
+ },
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
@@ -4001,6 +4048,20 @@
"integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==",
"dev": true
},
+ "node_modules/lowlight": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz",
+ "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==",
+ "license": "MIT",
+ "dependencies": {
+ "fault": "^1.0.0",
+ "highlight.js": "~10.7.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -4947,6 +5008,15 @@
"dev": true,
"peer": true
},
+ "node_modules/prismjs": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
+ "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -5103,6 +5173,23 @@
"react-dom": ">=18"
}
},
+ "node_modules/react-syntax-highlighter": {
+ "version": "15.6.6",
+ "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.6.tgz",
+ "integrity": "sha512-DgXrc+AZF47+HvAPEmn7Ua/1p10jNoVZVI/LoPiYdtY+OM+/nG5yefLHKJwdKqY1adMuHFbeyBaG9j64ML7vTw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.3.1",
+ "highlight.js": "^10.4.1",
+ "highlightjs-vue": "^1.0.0",
+ "lowlight": "^1.17.0",
+ "prismjs": "^1.30.0",
+ "refractor": "^3.6.0"
+ },
+ "peerDependencies": {
+ "react": ">= 0.14.0"
+ }
+ },
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@@ -5131,6 +5218,197 @@
"node": ">=8"
}
},
+ "node_modules/refractor": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz",
+ "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==",
+ "license": "MIT",
+ "dependencies": {
+ "hastscript": "^6.0.0",
+ "parse-entities": "^2.0.0",
+ "prismjs": "~1.27.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/@types/hast": {
+ "version": "2.3.10",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz",
+ "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2"
+ }
+ },
+ "node_modules/refractor/node_modules/@types/unist": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
+ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
+ "license": "MIT"
+ },
+ "node_modules/refractor/node_modules/character-entities": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
+ "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/character-entities-legacy": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
+ "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/character-reference-invalid": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
+ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/comma-separated-tokens": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
+ "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/hast-util-parse-selector": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz",
+ "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/refractor/node_modules/hastscript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz",
+ "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^2.0.0",
+ "comma-separated-tokens": "^1.0.0",
+ "hast-util-parse-selector": "^2.0.0",
+ "property-information": "^5.0.0",
+ "space-separated-tokens": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/refractor/node_modules/is-alphabetical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
+ "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/is-alphanumerical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
+ "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
+ "license": "MIT",
+ "dependencies": {
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/is-decimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
+ "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/is-hexadecimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
+ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/parse-entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
+ "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
+ "license": "MIT",
+ "dependencies": {
+ "character-entities": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "character-reference-invalid": "^1.0.0",
+ "is-alphanumerical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-hexadecimal": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/prismjs": {
+ "version": "1.27.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz",
+ "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/refractor/node_modules/property-information": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
+ "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==",
+ "license": "MIT",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/space-separated-tokens": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
+ "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/rehype-raw": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz",
@@ -6211,6 +6489,15 @@
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
"dev": true
},
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 8977493..dc90aaa 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -16,6 +16,7 @@
"@emotion/styled": "^11.14.1",
"@mui/icons-material": "^7.2.0",
"@mui/material": "^7.2.0",
+ "@types/react-syntax-highlighter": "^15.5.13",
"dayjs": "^1.11.13",
"imurmurhash": "^0.1.4",
"react": "^19.1.0",
@@ -23,6 +24,7 @@
"react-icons": "^5.5.0",
"react-markdown": "^10.1.0",
"react-router-dom": "^7.6.2",
+ "react-syntax-highlighter": "^15.6.6",
"rehype-raw": "^7.0.0",
"zustand": "^5.0.7"
},
diff --git a/frontend/src/components/codeblock/CodeBlock.test.tsx b/frontend/src/components/codeblock/CodeBlock.test.tsx
new file mode 100644
index 0000000..c3963a5
--- /dev/null
+++ b/frontend/src/components/codeblock/CodeBlock.test.tsx
@@ -0,0 +1,54 @@
+import { render, screen, fireEvent, waitFor } from "@testing-library/react";
+import { describe, it, expect, vi } from "vitest";
+import CodeBlock from "./CodeBlock";
+
+// Mock clipboard API
+Object.assign(navigator, {
+ clipboard: {
+ writeText: vi.fn(() => Promise.resolve()),
+ },
+});
+
+describe("CodeBlock", () => {
+ const sampleCode = `function hello() {
+ console.log("Hello, world!");
+}`;
+
+ it("renders code content", () => {
+ render();
+ expect(screen.getByText(/Hello, world!/)).toBeInTheDocument();
+ });
+
+ it("renders with syntax highlighting", () => {
+ render();
+ // Check that syntax highlighter is applied - it should create a pre element
+ const preElement = screen.getByRole("button").closest("[data-testid]") || document.querySelector("pre");
+ expect(preElement || screen.getByText(/Hello, world!/).closest("pre")).toBeInTheDocument();
+ });
+
+ it("copies code to clipboard when copy button is clicked", async () => {
+ const writeTextSpy = vi.spyOn(navigator.clipboard, "writeText");
+
+ render();
+
+ const copyButton = screen.getByRole("button");
+ fireEvent.click(copyButton);
+
+ expect(writeTextSpy).toHaveBeenCalledWith(sampleCode);
+
+ // Check tooltip changes to "Copied!" - it's in aria-label
+ await waitFor(() => {
+ expect(copyButton).toHaveAttribute("aria-label", "Copied!");
+ });
+ });
+
+ it("accepts language prop for syntax highlighting", () => {
+ render();
+ expect(screen.getByText(/Hello/)).toBeInTheDocument();
+ });
+
+ it("defaults to text language when no language specified", () => {
+ render();
+ expect(screen.getByText("plain text")).toBeInTheDocument();
+ });
+});
diff --git a/frontend/src/components/codeblock/CodeBlock.tsx b/frontend/src/components/codeblock/CodeBlock.tsx
index b5061a3..92b5686 100644
--- a/frontend/src/components/codeblock/CodeBlock.tsx
+++ b/frontend/src/components/codeblock/CodeBlock.tsx
@@ -3,17 +3,15 @@ import {
Box,
IconButton,
Tooltip,
- Typography,
useTheme,
- type SxProps,
- type Theme,
} from "@mui/material";
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
-import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
-import ExpandLessIcon from "@mui/icons-material/ExpandLess";
+import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
+import { oneLight } from "react-syntax-highlighter/dist/esm/styles/prism";
interface CodeBlockProps {
code: string;
+ language?: string;
maxHeight?: number | string;
}
@@ -34,7 +32,7 @@ const styles = {
},
};
-export default function CodeBlock({ code }: CodeBlockProps) {
+export default function CodeBlock({ code, language = "text" }: CodeBlockProps) {
const [copied, setCopied] = useState(false);
const theme = useTheme();
@@ -56,11 +54,9 @@ export default function CodeBlock({ code }: CodeBlockProps) {
- {/* Scrollable Code */}
+ {/* Scrollable Code with Syntax Highlighting */}
- {code}
+
+ {code}
+
);
diff --git a/frontend/src/pages/leaderboard/Leaderboard.test.tsx b/frontend/src/pages/leaderboard/Leaderboard.test.tsx
index 52bb457..cdfdb19 100644
--- a/frontend/src/pages/leaderboard/Leaderboard.test.tsx
+++ b/frontend/src/pages/leaderboard/Leaderboard.test.tsx
@@ -103,7 +103,8 @@ describe("Leaderboard", () => {
// Switch to Reference tab before asserting its content
fireEvent.click(referenceTab);
expect(screen.getByText(/Reference Implementation/i)).toBeInTheDocument();
- expect(screen.getByText(mockReference)).toBeInTheDocument();
+ expect(screen.getByText(/import/)).toBeInTheDocument();
+ expect(screen.getByText(/torch/)).toBeInTheDocument();
});
it("shows loading state", () => {
@@ -302,7 +303,8 @@ describe("Leaderboard", () => {
// Reference codeblock should be visible
expect(screen.getByText(/Reference Implementation/i)).toBeInTheDocument();
- expect(screen.getByText(mockReference)).toBeInTheDocument();
+ expect(screen.getByText(/import/)).toBeInTheDocument();
+ expect(screen.getByText(/torch/)).toBeInTheDocument();
});
// -------------------- Tabs behavior (switching) --------------------
@@ -343,7 +345,8 @@ describe("Leaderboard", () => {
// Switch to Reference tab
fireEvent.click(screen.getByRole("tab", { name: /Reference/i }));
expect(screen.getByText(/Reference Implementation/i)).toBeInTheDocument();
- expect(screen.getByText(mockReference)).toBeInTheDocument();
+ expect(screen.getByText(/import/)).toBeInTheDocument();
+ expect(screen.getByText(/torch/)).toBeInTheDocument();
// Switch back to Rankings tab
fireEvent.click(screen.getByRole("tab", { name: /Rankings/i }));
diff --git a/frontend/src/pages/leaderboard/Leaderboard.tsx b/frontend/src/pages/leaderboard/Leaderboard.tsx
index 5860de4..d428bea 100644
--- a/frontend/src/pages/leaderboard/Leaderboard.tsx
+++ b/frontend/src/pages/leaderboard/Leaderboard.tsx
@@ -176,7 +176,7 @@ export default function Leaderboard() {
Reference Implementation
-
+
From 08207bf97d63a503b313abf35ec24f91255c07b5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 30 Aug 2025 20:17:34 +0000
Subject: [PATCH 3/3] Simplify CodeBlock component for Python-only syntax
highlighting
Co-authored-by: msaroufim <3282513+msaroufim@users.noreply.github.com>
---
.../src/components/codeblock/CodeBlock.test.tsx | 13 +++++--------
frontend/src/components/codeblock/CodeBlock.tsx | 5 ++---
frontend/src/pages/leaderboard/Leaderboard.tsx | 2 +-
3 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/frontend/src/components/codeblock/CodeBlock.test.tsx b/frontend/src/components/codeblock/CodeBlock.test.tsx
index c3963a5..60a5fd5 100644
--- a/frontend/src/components/codeblock/CodeBlock.test.tsx
+++ b/frontend/src/components/codeblock/CodeBlock.test.tsx
@@ -19,8 +19,8 @@ describe("CodeBlock", () => {
expect(screen.getByText(/Hello, world!/)).toBeInTheDocument();
});
- it("renders with syntax highlighting", () => {
- render();
+ it("renders with Python syntax highlighting", () => {
+ render();
// Check that syntax highlighter is applied - it should create a pre element
const preElement = screen.getByRole("button").closest("[data-testid]") || document.querySelector("pre");
expect(preElement || screen.getByText(/Hello, world!/).closest("pre")).toBeInTheDocument();
@@ -42,13 +42,10 @@ describe("CodeBlock", () => {
});
});
- it("accepts language prop for syntax highlighting", () => {
- render();
+ it("handles Python code properly", () => {
+ render();
expect(screen.getByText(/Hello/)).toBeInTheDocument();
});
- it("defaults to text language when no language specified", () => {
- render();
- expect(screen.getByText("plain text")).toBeInTheDocument();
- });
+
});
diff --git a/frontend/src/components/codeblock/CodeBlock.tsx b/frontend/src/components/codeblock/CodeBlock.tsx
index 92b5686..f2dab23 100644
--- a/frontend/src/components/codeblock/CodeBlock.tsx
+++ b/frontend/src/components/codeblock/CodeBlock.tsx
@@ -11,7 +11,6 @@ import { oneLight } from "react-syntax-highlighter/dist/esm/styles/prism";
interface CodeBlockProps {
code: string;
- language?: string;
maxHeight?: number | string;
}
@@ -32,7 +31,7 @@ const styles = {
},
};
-export default function CodeBlock({ code, language = "text" }: CodeBlockProps) {
+export default function CodeBlock({ code }: CodeBlockProps) {
const [copied, setCopied] = useState(false);
const theme = useTheme();
@@ -76,7 +75,7 @@ export default function CodeBlock({ code, language = "text" }: CodeBlockProps) {
}}
>
Reference Implementation
-
+