diff --git a/package.json b/package.json index b29317a..613cb09 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "react-syntax-highlighter": "^15.4.5", "recoil": "^0.5.2", "recoil-persist": "^4.0.0", + "refractor": "3", "remark-gfm": "^3.0.1" }, "devDependencies": { @@ -37,6 +38,7 @@ "@types/react": "17.0.37", "@types/react-syntax-highlighter": "^13.5.2", "@types/recoil": "^0.0.9", + "@types/refractor": "^3.0.2", "eslint": "7", "eslint-config-next": "^12.0.4", "eslint-config-prettier": "^8.3.0", diff --git a/src/components/review/DiffRenderer.tsx b/src/components/review/DiffRenderer.tsx index 1674870..4005e18 100644 --- a/src/components/review/DiffRenderer.tsx +++ b/src/components/review/DiffRenderer.tsx @@ -1,6 +1,9 @@ +import path from "path"; + import { PlusSquareIcon } from "@chakra-ui/icons"; import { Box } from "@chakra-ui/react"; import { useMemo, useState } from "react"; +import refractor from "refractor"; import ReviewPopover from "@/components/review/Popover"; @@ -9,6 +12,7 @@ const Diff = reactDiffView.Diff; const Hunk = reactDiffView.Hunk; const Decoration = reactDiffView.Decoration; const getChangeKey = reactDiffView.getChangeKey; +const tokenize = reactDiffView.tokenize; type Props = { fileId: string; @@ -43,6 +47,22 @@ const DiffRenderer = ({ const [tmpChangeKey, setTmpChangeKey] = useState(""); const postPath: string = type === "delete" ? oldPath : newPath; + const tokens = useMemo(() => { + try { + return tokenize(hunks, { + highlight: true, + refractor: refractor, + language: path.extname(postPath).slice(1), + }); + } catch (e) { + // ・ファイル名の文字列 (postPath) が空文字の可能性のある初回ロード + // ・ライブラリ非対応の拡張子 + // の場合、refractor ライブラリがエラーを送出するので + // シンタックスハイライトを無効にする + return tokenize(hunks, { highlight: false }); + } + }, [hunks]); + const renderGutter = ({ side, renderDefault, @@ -76,6 +96,7 @@ const DiffRenderer = ({ viewType="unified" diffType={type} hunks={hunks} + tokens={tokens} widgets={widgets[fileId]} renderGutter={renderGutter} > diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 4fae16e..b6dddd8 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -5,6 +5,8 @@ import Head from "next/head"; import { RecoilRoot } from "recoil"; import { AuthProvider } from "@/components/AuthProvider"; + +import "prismjs/themes/prism.css"; import "@/style/difffile.css"; const MyApp: NextPage = ({ Component, pageProps }) => { diff --git a/yarn.lock b/yarn.lock index 0bede10..f0adea5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2178,6 +2178,11 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.3.tgz#a3c65525b91fca7da00ab1a3ac2b5a2a4afbffbf" integrity sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w== +"@types/prismjs@*": + version "1.26.0" + resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.0.tgz#a1c3809b0ad61c62cac6d4e0c56d610c910b7654" + integrity sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ== + "@types/prop-types@*": version "15.7.4" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" @@ -2206,6 +2211,13 @@ dependencies: recoil "*" +"@types/refractor@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/refractor/-/refractor-3.0.2.tgz#2d42128d59f78f84d2c799ffc5ab5cadbcba2d82" + integrity sha512-2HMXuwGuOqzUG+KUTm9GDJCHl0LCBKsB5cg28ujEmVi/0qgTb6jOmkVSO5K48qXksyl2Fr3C0Q2VrgD4zbwyXg== + dependencies: + "@types/prismjs" "*" + "@types/scheduler@*": version "0.16.2" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" @@ -6390,6 +6402,11 @@ prismjs@^1.25.0, prismjs@~1.25.0: resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756" integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg== +prismjs@~1.27.0: + version "1.27.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" + integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -6716,6 +6733,15 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +refractor@3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" + integrity sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA== + dependencies: + hastscript "^6.0.0" + parse-entities "^2.0.0" + prismjs "~1.27.0" + refractor@^3.2.0: version "3.5.0" resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.5.0.tgz#334586f352dda4beaf354099b48c2d18e0819aec"