Skip to content

Commit

Permalink
(v1.3.0): support locate source code
Browse files Browse the repository at this point in the history
  • Loading branch information
blucas.wu committed Aug 15, 2023
1 parent a6ca87c commit 1d54b8a
Show file tree
Hide file tree
Showing 32 changed files with 1,019 additions and 313 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ yarn-error.log*
/dist
/docs-dist
test.ts
public/page-spy/index.min.js
public/*
!public/favicon*

# misc
.DS_Store
Expand Down
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2022-present Blucas

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
12 changes: 12 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@
<title>PageSpy</title>
<link rel="icon" href="/favicon.ico">
<link rel="shortcut icon" type="image/svg+xml" href="/favicon.svg">
<script src="/source-map/source-map.min.js"></script>
<script>
const mappingWasmUrl = new URL('/source-map/mappings.wasm', window.location.href).toString()
sourceMap.SourceMapConsumer.initialize({
"lib/mappings.wasm": mappingWasmUrl
});
</script>
<script src="/shiki/dist/index.jsdelivr.iife.js"></script>
<script>
const shikiURL = new URL('/shiki', window.location.origin).toString()
window.shiki.setCDN(shikiURL)
</script>
</head>

<body>
Expand Down
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
{
"name": "@huolala-tech/page-spy-web",
"version": "1.2.7",
"version": "1.3.0",
"description": "All-In-One Remote Debugging Tool",
"homepage": "https://huolalatech.github.io/page-spy-web",
"license": "MIT",
"scripts": {
"start:doc": "vite --mode doc",
"prestart:client": "node scripts/mv-sdk.js",
"prestart:client": "bash scripts/public-files.sh",
"start:client": "vite --mode client",
"start:server": "page-spy-api",
"build:doc": "vite build --mode doc",
"prebuild:client": "node scripts/mv-sdk.js",
"prebuild:client": "bash scripts/public-files.sh",
"build:client": "vite build --mode client",
"preview": "vite preview",
"lint": "eslint --ext .js,.jsx,.ts,.tsx ./src"
},
"devDependencies": {
"@babel/eslint-parser": "^7.19.1",
"@huolala-tech/page-spy": "^1.2.5",
"@huolala-tech/page-spy": "^1.3.0",
"@mdx-js/rollup": "^2.3.0",
"@types/lodash-es": "^4.17.7",
"@types/mdx": "^2.0.4",
Expand Down Expand Up @@ -51,6 +51,7 @@
"antd": "^5.2.1",
"clsx": "^1.2.1",
"copy-to-clipboard": "^3.3.3",
"error-stack-parser": "^2.1.4",
"highlight.js": "^11.7.0",
"i18next": "^22.4.10",
"i18next-browser-languagedetector": "^7.0.1",
Expand All @@ -64,6 +65,8 @@
"react-transition-group": "^4.4.5",
"rehype-parse": "^8.0.4",
"rehype-stringify": "^9.0.3",
"shiki": "^0.14.3",
"source-map": "^0.7.4",
"unified": "^10.1.2",
"unist-util-visit": "^4.1.2",
"zustand": "^4.3.7"
Expand Down
28 changes: 21 additions & 7 deletions scripts/mv-sdk.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,30 @@ const fs = require('fs');
const path = require('path');

const root = process.cwd();
const targetDir = path.resolve(root, `public/page-spy`);

try {
fs.mkdirSync(targetDir, { recursive: true });
const pageSpy = require.resolve('@huolala-tech/page-spy');
const sourceMap = require.resolve('source-map');
const fileList = [
{
from: pageSpy,
to: path.resolve(root, 'public/page-spy/index.min.js'),
},
{
from: path.resolve(path.dirname(sourceMap), './dist/source-map.js'),
to: path.resolve(root, 'public/source-map/source-map.min.js'),
},
{
from: path.resolve(path.dirname(sourceMap), './lib/mappings.wasm'),
to: path.resolve(root, 'public/source-map/mappings.wasm'),
},
];

const src = require.resolve('@huolala-tech/page-spy');
const dest = path.resolve(targetDir, 'index.min.js');
fs.copyFileSync(src, dest);
try {
fileList.forEach(({ from, to }) => {
fs.mkdirSync(path.dirname(to), { recursive: true });
fs.copyFileSync(from, to);
});
} catch (e) {
console.error('PageSpy sdk copy failed.');
console.error(e);
process.exit(1);
}
17 changes: 17 additions & 0 deletions scripts/public-files.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

root=$(pwd)

# SDK
target_sdk="${root}/public/page-spy"
mkdir -p "$target_sdk"
cp "${root}/node_modules/@huolala-tech/page-spy/dist/index.min.js" "${root}/public/page-spy/index.min.js"

# source-map
target_sourcemap="${root}/public/source-map"
mkdir -p "$target_sourcemap"
cp "${root}/node_modules/source-map/dist/source-map.js" "${root}/public/source-map/source-map.min.js"
cp "${root}/node_modules/source-map/lib/mappings.wasm" "${root}/public/source-map/mappings.wasm"

# shiki
cp -R "${root}/node_modules/shiki" "${root}/public/shiki"
1 change: 1 addition & 0 deletions src/assets/image/error-stack.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 15 additions & 1 deletion src/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,21 @@
"console": {
"run": "Run",
"placeholder": "Executable code",
"newContent": "New content"
"newContent": "New content",
"error-trace": {
"title": "Error detail",
"hints": "HINTS",
"message-title": "Error message",
"stack-title": "Error stack",
"source-filename": "Source filename",
"fetch-minify-fail": "Fail to fetch origin file",
"none-sourcemap": "No sourcemap file founded",
"fetch-sourcemap-fail": "Fail to fetch sourcemap file",
"failed-title": "There are some issues with locating the source code",
"failed-advice": "Here are some suggestions to fix and improve the situation:",
"fix-suggestion-1": "<0>1. Ensure file existence: When locating the source code for each error stack, two files need to be requested - the compressed file and the sourcemap file. The rule for obtaining the sourcemap file is based on the address indicated by</0> <1>//# sourceMappingURL=*</1> <2>in the contents of the compressed file;</2>",
"fix-suggestion-2": "2. Troubleshoot network issues: If there are access restrictions on the server where your source files are located, it may lead to failed requests when trying to access the resources. You can open the devtool to check if the network is working properly."
}
},
"network": {},
"system": {
Expand Down
16 changes: 15 additions & 1 deletion src/assets/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,21 @@
"console": {
"run": "执行",
"placeholder": "可执行代码",
"newContent": "新消息"
"newContent": "新消息",
"error-trace": {
"title": "错误详情",
"hints": "使用须知",
"message-title": " 错误信息",
"stack-title": "错误栈",
"source-filename": "源文件",
"fetch-minify-fail": "获取源文件失败",
"none-sourcemap": "未找到 SourceMap",
"fetch-sourcemap-fail": "获取 SourceMap 失败",
"failed-title": "定位源码时出现一些故障",
"failed-advice": "以下是修复和改进的建议:",
"fix-suggestion-1": "<0>1. 确保文件存在:每个错误栈定位源码时都需要请求两个文件,分别是压缩文件和 sourcemap 文件,sourcemap 文件的获取规则是根据压缩文件内容中的</0><1>//# sourceMappingURL=*</1><2>所指向的地址;</2>",
"fix-suggestion-2": "2. 排除网络故障:如果你的源文件所在服务器有限制访问规则,则可能导致请求资源时出现失败,你可以打开控制台查看网络请求是否正常。"
}
},
"network": {},
"system": {
Expand Down
18 changes: 18 additions & 0 deletions src/components/BlockTitle/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.block-title {
position: relative;
padding-left: 16px;
&::before {
content: ' ';
display: block;
position: absolute;
left: 0;
top: 50%;
width: 4px;
height: 60%;
transform: translateY(-50%);
background-color: @primary-color;
}
~ .block-title {
margin-top: 32px;
}
}
21 changes: 21 additions & 0 deletions src/components/BlockTitle/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Typography } from 'antd';
import type { TitleProps } from 'antd/lib/typography/Title';
import './index.less';

const { Title } = Typography;

export const BlockTitle = ({
title,
level = 3,
}: {
title: React.ReactNode;
level?: TitleProps['level'];
}) => {
return (
<div className="block-title">
<Title level={level} style={{ color: 'rgba(0, 0, 0, 0.65)' }}>
{title}
</Title>
</div>
);
};
6 changes: 4 additions & 2 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import ReactDOM from 'react-dom';
import ReactDOM from 'react-dom/client';
import { App } from './App';
import '@/assets/style/union.less';
import '@/assets/style/initial.css';
import '@/assets/locales/index';

ReactDOM.render(<App />, document.querySelector('#root'));
const root = ReactDOM.createRoot(document.querySelector('#root')!);

root.render(<App />);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.error-trace {
display: flex;
flex-wrap: nowrap;
align-items: flex-start;

&-node {
flex: 1;
padding-inline: 8px;
}

&-icon {
color: #bbb;
font-size: 20px;
cursor: pointer;
&:hover {
color: #999;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { SpyConsole } from '@huolala-tech/page-spy';
import { ReactComponent as ErrorStackSvg } from '@/assets/image/error-stack.svg';
import './index.less';
import Icon from '@ant-design/icons';
import { useCallback } from 'react';
import ErrorStackParser from 'error-stack-parser';

export type RequiredFrames = Required<StackFrame>[];

export const isErrorTraceNode = (
item: SpyConsole.DataItem,
): item is RRequired<SpyConsole.DataItem> => {
if (
item.logType === 'error' &&
item.logs.length === 1 &&
item.errorDetail &&
item.errorDetail.stack
) {
return true;
}
return false;
};

export const ErrorTraceNode = ({
data,
}: {
data: RRequired<SpyConsole.DataItem>;
}) => {
const onPopupDetail = useCallback(() => {
if (!data.errorDetail.stack) {
return;
}

const error = new Error();

const { name, message, stack } = data.errorDetail;
error.name = name;
error.message = message;
error.stack = stack;
const frames = ErrorStackParser.parse(error).filter(
({ fileName, lineNumber, columnNumber }) => {
return [fileName, lineNumber, columnNumber].every(Boolean);
},
) as RequiredFrames;
if (!frames.length) return;

window.dispatchEvent(
new CustomEvent('source-code-detail', {
detail: {
error,
frames,
},
}),
);
}, [data.errorDetail]);

return (
<div className="error-trace">
<Icon
component={ErrorStackSvg}
className="error-trace-icon"
onClick={onPopupDetail}
/>
<div className="error-trace-node">
<code>{data.errorDetail.stack}</code>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.console-node {
margin-right: 7px;
font-size: 12px;
word-break: break-word;
&.origin {
color: #323941;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable no-underscore-dangle */
import type { ReactNode } from 'react';
import type { MouseEventHandler, ReactNode } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { CaretRightOutlined } from '@ant-design/icons';
import './index.less';
Expand Down Expand Up @@ -34,7 +34,7 @@ function GetterNode({ id, parentId, instanceId, keyName }: GetterNodeProps) {
};
}, [id, keyName, socket]);

const getPropertyValue = useCallback(
const getPropertyValue: MouseEventHandler = useCallback(
(evt) => {
if (!id) return;
evt.stopPropagation();
Expand Down Expand Up @@ -152,7 +152,7 @@ const PropertyItem = React.memo<{
const PrototypeKey = '[[Prototype]]';
interface AtomNodeProps {
id: string;
value: string | PropertyDescriptor | ReactNode;
value: string | ReactNode;
showArrow?: boolean;
}
function AtomNode({ id, value, showArrow = true }: AtomNodeProps) {
Expand Down Expand Up @@ -236,7 +236,7 @@ interface ConsoleNodeProps {
const ConsoleNode = React.memo<ConsoleNodeProps>(({ data }) => {
const { __atomId = '', type, value } = data;
if (type === 'atom' && !!__atomId) {
return <AtomNode id={__atomId} value={value} />;
return <AtomNode id={__atomId} value={value as string} />;
}
// new Boolean/String/Number...
// e.g. new Boolean() => { type: 'object', value: false }
Expand Down
Loading

0 comments on commit 1d54b8a

Please sign in to comment.