, cutName: string, char: string) => {
+ const index = cutName.search(char);
+ if (index > -1) {
+ const notHighlightStr = cutName.slice(0, index);
+ showName.push(
+
+ {notHighlightStr}
+ {{char}}
+ {cutName.slice(index + char.length)}
+
+ );
+ } else {
+ pushBadge(showName, cutName);
+ }
+ };
+
+ const reg = createRegExp(highlightValue);
+ const heightCharacters = name.itemName.match(reg);
+ const showName = [];
+
+ const addShowName = (showName: Array, name: NameObj) => {
+ showName.push(`<${name.itemName}>`);
+ name.badge.forEach(key => {
+ showName.push({key}
);
+ });
+ };
+
+ if (heightCharacters) {
+ // 高亮第一次匹配即可
+ const char = heightCharacters[0];
+ pushItemName(showName, name.itemName, char);
+ if (name.badge.length > 0) {
+ name.badge.forEach(key => {
+ pushBadgeName(showName, key, char);
+ });
+ }
+ } else {
+ addShowName(showName, name);
+ }
+
+ return (
+
+
+ {showIcon}
+
+
{showName}
+ {isShowKey && (
+ <>
+
key
+ {'="'}
+
{userKey}
+ {'"'}
+ >
+ )}
+
+ );
+}
+
+function VTree(props: {
+ data: IData[];
+ maxDeep: number;
+ highlightValue: string;
+ scrollToItem: IData;
+ onRendered: (renderInfo: RenderInfoType) => void;
+ collapsedNodes?: IData[];
+ onCollapseNode?: (item: IData[]) => void;
+ selectItem: IData;
+ onSelectItem: (item: IData) => void;
+}) {
+ const {
+ data,
+ maxDeep,
+ highlightValue,
+ scrollToItem,
+ onRendered,
+ onCollapseNode,
+ onSelectItem
+ } = props;
+ const [collapseNode, setCollapseNode] = useState(props.collapsedNodes || []);
+ const [selectItem, setSelectItem] = useState(props.selectItem);
+ const [childItems, setChildItems] = useState>([]);
+
+ useEffect(() => {
+ setSelectItem(scrollToItem);
+ }, [scrollToItem]);
+
+ useEffect(() => {
+ if (props.selectItem !== selectItem) {
+ setSelectItem(props.selectItem);
+ }
+ }, [props.selectItem]);
+
+ useEffect(() => {
+ setCollapseNode(props.collapsedNodes || []);
+ }, [props.collapsedNodes]);
+
+ const changeCollapseNode = (item: IData) => {
+ const nodes: IData[] = [...collapseNode];
+ const index = nodes.indexOf(item);
+ if (index === -1) {
+ nodes.push(item);
+ } else {
+ nodes.splice(index, 1);
+ }
+
+ setCollapseNode(nodes);
+
+ if (onCollapseNode) {
+ onCollapseNode(nodes);
+ }
+ };
+
+ const getChildItem = (item: IData): Array => {
+ const index = data.indexOf(item);
+ const childList: Array = [];
+
+ for (let i = index + 1; i < data.length; i++) {
+ if (data[i].indentation > item.indentation) {
+ childList.push(data[i]);
+ } else {
+ break;
+ }
+ }
+ return childList;
+ };
+
+ const handleClickItem = useCallback(
+ (item: IData) => {
+ const childItem = getChildItem(item);
+ setSelectItem(item);
+ setChildItems(childItem);
+ if (onSelectItem) {
+ onSelectItem(item);
+ }
+ },
+ [onSelectItem]
+ );
+
+ const handleMouseEnterItem = useCallback(
+ item => {
+ postMessageToBackground(Highlight, item);
+ },
+ null
+ );
+
+ const handleMouseLeaveItem = () => {
+ postMessageToBackground(RemoveHighlight);
+ };
+
+ let currentCollapseIndentation: null | number = null;
+ // 过滤掉折叠的 item,不展示在 VList 中
+ const filter = (item: IData) => {
+ if (currentCollapseIndentation !== null) {
+ // 缩进更大,不显示
+ if (item.indentation > currentCollapseIndentation) {
+ return false;
+ } else {
+ // 缩进小,说明完成了收起节点的子节点处理
+ currentCollapseIndentation = null;
+ }
+ }
+ const isCollapsed = collapseNode.includes(item);
+ if (isCollapsed) {
+ // 该节点需要收起子节点
+ currentCollapseIndentation = item.indentation;
+ }
+ return true;
+ };
+
+ const showList = data.filter(filter);
+
+ return (
+
+ {(width: number, height: number) => {
+ return (
+
+ {(item: IData, indentationLength: number) => {
+ const isCollapsed = collapseNode.includes(item);
+ const index = showList.indexOf(item);
+ // 如果收起,一定有 child
+ // 不收起场景,如果存在下一个节点,并且节点缩进比自己大,说明下个节点是子节点,节点本身需要显示展开收起图标
+ const hasChild = isCollapsed || showList[index + 1]?.indentation > item.indentation;
+ return (
+
+ );
+ }}
+
+ );
+ }}
+
+ );
+}
+
+export default memo(VTree);
diff --git a/packages/inula-dev-tools/src/components/assets.less b/packages/inula-dev-tools/src/components/assets.less
new file mode 100644
index 00000000..918c1291
--- /dev/null
+++ b/packages/inula-dev-tools/src/components/assets.less
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023 Huawei Technologies Co.,Ltd.
+ *
+ * openInula is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *
+ * http://license.coscl.org.cn/MulanPSL2
+ *
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+@arrow-color: rgb(95, 99, 104);
+@divider-color: rgb(202, 205, 209);
+@attr-name-color: rgb(200, 0, 0);
+@component-name-color: rgb(136, 18, 128);
+@component-key-color: rgb(153, 69, 0);
+@component-key-value-color: rgb(26, 26, 166);
+@component-attr-color: rgb(200, 0, 0);
+@select-color: rgb(144 199 248 / 60%);
+@select-item-child-color: rgb(141 199 248 / 40%);
+@hover-color: black;
+
+@top-height: 2.625rem;
+@divider-width: 0.2px;
+@common-font-size: 12px;
+
+@divider-style: @divider-color solid @divider-width;
+@attr-name-font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
diff --git a/packages/inula-dev-tools/src/panelConnection/index.ts b/packages/inula-dev-tools/src/panelConnection/index.ts
new file mode 100644
index 00000000..96234936
--- /dev/null
+++ b/packages/inula-dev-tools/src/panelConnection/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2023 Huawei Technologies Co.,Ltd.
+ *
+ * openInula is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *
+ * http://license.coscl.org.cn/MulanPSL2
+ *
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+export * from './panelConnection';
diff --git a/packages/inula-dev-tools/src/panelConnection/panelConnection.ts b/packages/inula-dev-tools/src/panelConnection/panelConnection.ts
new file mode 100644
index 00000000..56941206
--- /dev/null
+++ b/packages/inula-dev-tools/src/panelConnection/panelConnection.ts
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2023 Huawei Technologies Co.,Ltd.
+ *
+ * openInula is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *
+ * http://license.coscl.org.cn/MulanPSL2
+ *
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+import { packagePayload } from '../utils/transferUtils';
+import { DevToolPanel, InitDevToolPageConnection } from '../utils/constants';
+
+let connection;
+const callbacks = [];
+
+export function addBackgroundMessageListener(func: (message) => void) {
+ callbacks.push(func);
+}
+
+export function removeBackgroundMessageListener(func: (message) => void) {
+ const index = callbacks.indexOf(func);
+ if (index !== -1) {
+ callbacks.splice(index, 1);
+ }
+}
+
+export function initBackgroundConnection(type) {
+ if (!isDev) {
+ try {
+ connection = chrome.runtime.connect({ name: type });
+ const notice = message => {
+ callbacks.forEach(func => {
+ func(message);
+ });
+ };
+ // 监听 background 消息
+ connection.onMessage.addListener(notice);
+ // 页面打开后发送初始化请求
+ postMessageToBackground(InitDevToolPageConnection);
+ } catch (e) {
+ console.error('create connection failer');
+ console.error(e);
+ }
+ }
+}
+
+let reconnectionTimes = 0;
+export function postMessageToBackground(
+ type: string,
+ data?: any,
+ inulaX?: boolean
+) {
+ try {
+ const payload = data
+ ? { type, tabId: chrome.devtools.inspectedWindow.tabId, data }
+ : { type, tabId: chrome.devtools.inspectedWindow.tabId };
+ connection.postMessage(packagePayload(payload, DevToolPanel));
+ } catch (e) {
+ // 可能出现 port 关闭的场景,需要重新建立连接,增加可靠性
+ if (reconnectionTimes === 20) {
+ reconnectionTimes = 0;
+ console.error('reconnect failed');
+ return;
+ }
+ console.error(e);
+ reconnectionTimes++;
+ // 重新连接
+ initBackgroundConnection(inulaX ? 'panelX' : 'panel');
+ // 初始化成功后才会重新发送消息
+ postMessageToBackground(type, data);
+ }
+}
diff --git a/packages/inula-dev-tools/tsconfig.json b/packages/inula-dev-tools/tsconfig.json
index d0c62d99..d07996f8 100644
--- a/packages/inula-dev-tools/tsconfig.json
+++ b/packages/inula-dev-tools/tsconfig.json
@@ -2,7 +2,6 @@
"compilerOptions": {
"outDir": "./dist",
"allowJs": true,
- "strict": true,
"noImplicitAny": false,
"module": "es6",
"moduleResolution": "node",
@@ -16,6 +15,6 @@
}
},
"include": [
- "./src/**/*.ts", "./src/index.d.ts", "./src/**/*.tsx", "./externals.d.ts"
+ "./src/**/*.ts", "./src/index.d.ts", "./src/**/*.tsx", "./externals.d.ts", "./global.d.ts"
]
}