From 714f17d60d518f7e3dad46baee36db5e1e50fe4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allen=20Zhang=20=28=E5=BC=A0=E6=B6=9B=29?= Date: Sun, 29 Sep 2024 14:37:23 +0800 Subject: [PATCH] feat: update shiki --- .../components/CanyonReport/ShikiDetail.tsx | 62 ++++++++++--------- .../src/components/CanyonReport/loadShiki.ts | 18 ++++++ .../src/components/app/CopyCode.tsx | 13 ++-- packages/canyon-report/package.json | 1 + .../src/components/Report/Report.tsx | 61 +++++++++--------- .../Report/components/FileCoverageDetail.tsx | 17 +++-- .../Report/components/SummaryHeader.tsx | 16 ++++- .../Report/components/SummaryListTable.tsx | 18 +++--- .../Report/components/TopControl.tsx | 4 +- .../src/components/Report/types.ts | 9 +++ .../src/components/helpers/index.ts | 9 +++ .../src/components/helpers/loadShiki.ts | 18 ++++++ packages/canyon-report/src/index.css | 5 ++ 13 files changed, 163 insertions(+), 88 deletions(-) create mode 100644 packages/canyon-platform/src/components/CanyonReport/loadShiki.ts create mode 100644 packages/canyon-report/src/components/Report/types.ts create mode 100644 packages/canyon-report/src/components/helpers/index.ts create mode 100644 packages/canyon-report/src/components/helpers/loadShiki.ts diff --git a/packages/canyon-platform/src/components/CanyonReport/ShikiDetail.tsx b/packages/canyon-platform/src/components/CanyonReport/ShikiDetail.tsx index c419c9ff..8f8637b8 100644 --- a/packages/canyon-platform/src/components/CanyonReport/ShikiDetail.tsx +++ b/packages/canyon-platform/src/components/CanyonReport/ShikiDetail.tsx @@ -1,5 +1,5 @@ -import { codeToHtml } from "shiki"; import { mergeIntervals } from "./helper.tsx"; +import { createHighlighterCoreInstance } from "@/components/CanyonReport/loadShiki.ts"; const ShikiDetail = ({ defaultValue, filecoverage, theme }) => { const [content, setContent] = useState(""); @@ -87,40 +87,42 @@ const ShikiDetail = ({ defaultValue, filecoverage, theme }) => { } }); - codeToHtml(defaultValue, { - lang: "javascript", - theme: theme === "light" ? "light-plus" : "tokyo-night", - decorations: mergeIntervals( - [...statementDecorations, ...fnDecorations].filter((item) => { - // defaultValue - if (item[0] >= item[1]) { - return false; - } else if (item[1] > defaultValue.length) { - return false; - } else { - return item[0] < item[1]; - } - }), - ).map(([start, end]) => { - return { - start, - end, - properties: { class: "content-class-no-found" }, - }; - }), - }) - .then((res) => { + createHighlighterCoreInstance().then(({ codeToHtml }) => { + try { + const res = codeToHtml(defaultValue, { + lang: "javascript", + theme: theme === "light" ? "light-plus" : "tokyo-night", + decorations: mergeIntervals( + [...statementDecorations, ...fnDecorations].filter((item) => { + // defaultValue + if (item[0] >= item[1]) { + return false; + } else if (item[1] > defaultValue.length) { + return false; + } else { + return item[0] < item[1]; + } + }), + ).map(([start, end]) => { + return { + start, + end, + properties: { class: "content-class-no-found" }, + }; + }), + }); setContent(res); - }) - .catch((err) => { + } catch (err) { console.log("覆盖率着色失败", err); - codeToHtml(defaultValue, { + const r = codeToHtml(defaultValue, { lang: "javascript", theme: theme === "light" ? "light-plus" : "tokyo-night", - }).then((r) => { - setContent(r); }); - }); + + setContent(r); + } + }); + return (
diff --git a/packages/canyon-platform/src/components/CanyonReport/loadShiki.ts b/packages/canyon-platform/src/components/CanyonReport/loadShiki.ts new file mode 100644 index 00000000..9b2a59e1 --- /dev/null +++ b/packages/canyon-platform/src/components/CanyonReport/loadShiki.ts @@ -0,0 +1,18 @@ +import { createHighlighterCore } from "shiki/core"; +import getWasm from "shiki/wasm"; +import lightplus from "shiki/themes/light-plus.mjs"; +import css from "shiki/langs/css.mjs"; +import jscss from "shiki/langs/javascript.mjs"; +import { createOnigurumaEngine } from "shiki/engine/oniguruma"; + +export const createHighlighterCoreInstance = async () => { + return await createHighlighterCore({ + themes: [ + // 传入导入的包,而不是字符串 + lightplus, + ], + langs: [css, jscss], + // `shiki/wasm` contains the wasm binary inlined as base64 string. + engine: createOnigurumaEngine(getWasm), + }); +}; diff --git a/packages/canyon-platform/src/components/app/CopyCode.tsx b/packages/canyon-platform/src/components/app/CopyCode.tsx index aeda2459..f8aa8d70 100755 --- a/packages/canyon-platform/src/components/app/CopyCode.tsx +++ b/packages/canyon-platform/src/components/app/CopyCode.tsx @@ -1,10 +1,10 @@ import "./CopyCode.css"; import { CopyOutlined } from "@ant-design/icons"; -import { codeToHtml } from "shiki"; import { FC, useEffect } from "react"; // @ts-ignore import { CopyToClipboard } from "react-copy-to-clipboard"; +import { createHighlighterCoreInstance } from "@/components/CanyonReport/loadShiki.ts"; const CopyCode: FC<{ code: string }> = ({ code }) => { const fileContent = code; @@ -12,11 +12,12 @@ const CopyCode: FC<{ code: string }> = ({ code }) => { useEffect(() => { if (fileContent) { - codeToHtml(fileContent, { - lang: "json", - theme: "tokyo-night", - }).then((r) => { - setContent(r); + createHighlighterCoreInstance().then(({ codeToHtml }) => { + const html = codeToHtml(fileContent, { + lang: "json", + theme: "tokyo-night", + }); + setContent(html); }); } }, [fileContent]); diff --git a/packages/canyon-report/package.json b/packages/canyon-report/package.json index 7466b573..d410be56 100755 --- a/packages/canyon-report/package.json +++ b/packages/canyon-report/package.json @@ -29,6 +29,7 @@ "shiki": "^1.18.0" }, "devDependencies": { + "@types/istanbul-lib-coverage": "^2.0.6", "@types/react": "^18.3.8", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^8.7.0", diff --git a/packages/canyon-report/src/components/Report/Report.tsx b/packages/canyon-report/src/components/Report/Report.tsx index 49e6b258..598b12f2 100644 --- a/packages/canyon-report/src/components/Report/Report.tsx +++ b/packages/canyon-report/src/components/Report/Report.tsx @@ -1,32 +1,32 @@ -// @ts-nocheck -import React from "react"; +import React, { FC } from "react"; import SummaryHeader from "./components/SummaryHeader"; import { useEffect, useMemo, useState } from "react"; import SummaryListTable from "./components/SummaryListTable"; -// import { Button, Table } from "antd"; import TopControl from "./components/TopControl"; import FileCoverageDetail from "./components/FileCoverageDetail"; -// import { codeToHtml } from "shiki"; +import { ReportProps } from "./types"; +import { FileCoverageData } from "istanbul-lib-coverage"; -/** - * 这是一个示例组件。 - * @param {Object} props - 组件的属性。 - * @param {string} props.name - 名称。 - * @param {number} props.age - 年龄。 - */ -// eslint-disable-next-line react/prop-types -function Report({ dataSource, value, loading, onSelect, loadData }) { +const Report: FC = ({ dataSource, value, onSelect }) => { const isFile = useMemo(() => { return value.includes("."); }, [value]); - const [fileCoverage, setFileCoverage] = useState(null); - const [fileContent, setFileContent] = useState(null); - - function newonSelect(val) { + const [, setFileCoverage] = useState({ + path: "", + statementMap: {}, + fnMap: {}, + branchMap: {}, + s: {}, + f: {}, + b: {}, + }); + const [fileContent, setFileContent] = useState(""); + + function newonSelect(val: string) { return onSelect(val).then((res) => { - setFileContent(res?.fileContent); - setFileCoverage(res?.fileCoverage); + setFileContent(res.fileContent); + setFileCoverage(res.fileCoverage); return res; }); } @@ -37,25 +37,26 @@ function Report({ dataSource, value, loading, onSelect, loadData }) { return (
- + { + return item.path.startsWith(value); + }).length + } + /> {isFile ? ( ) : ( - + )} - {/*{JSON.stringify(dataSource)}*/} - {/*
*/} - - {/**/} - {/**/} ); -} +}; export default Report; diff --git a/packages/canyon-report/src/components/Report/components/FileCoverageDetail.tsx b/packages/canyon-report/src/components/Report/components/FileCoverageDetail.tsx index 48008735..a56d4b43 100644 --- a/packages/canyon-report/src/components/Report/components/FileCoverageDetail.tsx +++ b/packages/canyon-report/src/components/Report/components/FileCoverageDetail.tsx @@ -1,18 +1,17 @@ // @ts-nocheck import React from "react"; -// import { codeToHtml } from 'https://esm.sh/shiki@1.0.0' import { useEffect, useState } from "react"; -import { codeToHtml } from "shiki"; +import { createHighlighterCoreInstance } from "../../helpers/loadShiki"; + const FileCoverageDetail = ({ fileContent }) => { - // console.log(fileContent); const [htmlContent, setHtmlContent] = useState(""); useEffect(() => { - codeToHtml(fileContent || "", { - lang: "javascript", - theme: "light-plus", - }).then((r) => { - console.log(r); - setHtmlContent(r); + createHighlighterCoreInstance().then((highlighter) => { + const html = highlighter.codeToHtml(fileContent || "", { + lang: "javascript", + theme: "light-plus", + }); + setHtmlContent(html); }); }, [fileContent]); return ( diff --git a/packages/canyon-report/src/components/Report/components/SummaryHeader.tsx b/packages/canyon-report/src/components/Report/components/SummaryHeader.tsx index c51f9e47..f3f5f271 100644 --- a/packages/canyon-report/src/components/Report/components/SummaryHeader.tsx +++ b/packages/canyon-report/src/components/Report/components/SummaryHeader.tsx @@ -1,6 +1,7 @@ // @ts-nocheck import React from "react"; -import { Tag,Typography } from "antd"; +import { Tag, Typography } from "antd"; +import {getColor} from "../../helpers"; const { Text } = Typography; const SummaryNav = ({ value, onClick }) => { console.log(value, "value"); @@ -52,7 +53,7 @@ const SummaryMetric = () => { {value.pct}% - {t("projects." + key)}: + {t(key)}: {value.covered}/{value.total} @@ -65,7 +66,16 @@ const SummaryMetric = () => { ); }; -const SummaryBar = () => {}; +const SummaryBar = () => { + return ( +
+ ); +}; const SummaryHeader = ({ value, onSelect }) => { console.log(value, "value"); diff --git a/packages/canyon-report/src/components/Report/components/SummaryListTable.tsx b/packages/canyon-report/src/components/Report/components/SummaryListTable.tsx index c4652839..0ac9daca 100644 --- a/packages/canyon-report/src/components/Report/components/SummaryListTable.tsx +++ b/packages/canyon-report/src/components/Report/components/SummaryListTable.tsx @@ -2,10 +2,11 @@ import { Table, Progress } from "antd"; import React from "react"; import Highlighter from "react-highlight-words"; +import { getColor } from "../../helpers"; // import { getCOlor, percent } from "../helper"; const t = (msg) => msg; -const SummaryListTable = ({ dataSource, onSelect }) => { +const SummaryListTable = ({ dataSource, onSelect, value }) => { return (
{ defaultPageSize: 15, }} size={"small"} - dataSource={dataSource} + dataSource={dataSource.filter((item) => { + return item.path.startsWith(value); + })} columns={[ { - title: t("projects.detail.files"), + title: t("Files"), key: "path", dataIndex: "path", - // width: '200px', render(text) { return ( { }, }, { - title: t("common.total"), + title: t("Total"), key: "total", dataIndex: ["statements", "total"], sorter(a, b) { @@ -50,7 +52,7 @@ const SummaryListTable = ({ dataSource, onSelect }) => { }, }, { - title: t("common.covered"), + title: t("Covered"), key: "covered", dataIndex: ["statements", "covered"], sorter(a, b) { @@ -59,7 +61,7 @@ const SummaryListTable = ({ dataSource, onSelect }) => { }, ].concat([ { - title: t("projects.config.coverage") + " %", + title: t("Coverage") + " %", width: "300px", key: "c", sorter: (a, b) => { @@ -72,7 +74,7 @@ const SummaryListTable = ({ dataSource, onSelect }) => { percent={text} strokeLinecap="butt" size={"small"} - strokeColor={"green"} + strokeColor={getColor(text)} className={"pr-5"} status={"normal"} /> diff --git a/packages/canyon-report/src/components/Report/components/TopControl.tsx b/packages/canyon-report/src/components/Report/components/TopControl.tsx index 832aa9a4..f3ae7bb2 100644 --- a/packages/canyon-report/src/components/Report/components/TopControl.tsx +++ b/packages/canyon-report/src/components/Report/components/TopControl.tsx @@ -3,7 +3,7 @@ import React from "react"; import Icon, { BarsOutlined, SearchOutlined } from "@ant-design/icons"; import { Divider, Space, Segmented, Input } from "antd"; -const TopControl = () => { +const TopControl = ({total}) => { const t = (msg) => msg; return (
@@ -31,7 +31,7 @@ const TopControl = () => { /> - 899 total files + {total} total files {/*{t("projects.detail.total.files", {msg: numberFiles})}*/} {/*覆盖率提升优先级列表*/} {/*转换生产流量为测试用例*/} diff --git a/packages/canyon-report/src/components/Report/types.ts b/packages/canyon-report/src/components/Report/types.ts new file mode 100644 index 00000000..e50825cb --- /dev/null +++ b/packages/canyon-report/src/components/Report/types.ts @@ -0,0 +1,9 @@ +import { CoverageSummaryData, FileCoverageData } from "istanbul-lib-coverage"; + +export interface ReportProps { + dataSource: (CoverageSummaryData & { path: string })[]; + value: string; // 当前选中的文件 + onSelect: ( + val: string, + ) => Promise<{ fileCoverage: FileCoverageData; fileContent: string }>; +} diff --git a/packages/canyon-report/src/components/helpers/index.ts b/packages/canyon-report/src/components/helpers/index.ts new file mode 100644 index 00000000..586e4a85 --- /dev/null +++ b/packages/canyon-report/src/components/helpers/index.ts @@ -0,0 +1,9 @@ +export const getColor = (pct: number) => { + if (pct >= 80) { + return "rgb(33,181,119)"; + } else if (pct >= 50) { + return "rgb(244,176,27)"; + } else { + return "rgb(245,32,32)"; + } +}; diff --git a/packages/canyon-report/src/components/helpers/loadShiki.ts b/packages/canyon-report/src/components/helpers/loadShiki.ts new file mode 100644 index 00000000..9b2a59e1 --- /dev/null +++ b/packages/canyon-report/src/components/helpers/loadShiki.ts @@ -0,0 +1,18 @@ +import { createHighlighterCore } from "shiki/core"; +import getWasm from "shiki/wasm"; +import lightplus from "shiki/themes/light-plus.mjs"; +import css from "shiki/langs/css.mjs"; +import jscss from "shiki/langs/javascript.mjs"; +import { createOnigurumaEngine } from "shiki/engine/oniguruma"; + +export const createHighlighterCoreInstance = async () => { + return await createHighlighterCore({ + themes: [ + // 传入导入的包,而不是字符串 + lightplus, + ], + langs: [css, jscss], + // `shiki/wasm` contains the wasm binary inlined as base64 string. + engine: createOnigurumaEngine(getWasm), + }); +}; diff --git a/packages/canyon-report/src/index.css b/packages/canyon-report/src/index.css index b5c61c95..a106642d 100644 --- a/packages/canyon-report/src/index.css +++ b/packages/canyon-report/src/index.css @@ -1,3 +1,8 @@ @tailwind base; @tailwind components; @tailwind utilities; + +.shiki > code { + font-size: 12px; + line-height: 20px; +}