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;
+}