Browse Source

完成css解析

杨东明 9 tháng trước cách đây
mục cha
commit
5424ee7416
4 tập tin đã thay đổi với 336 bổ sung225 xóa
  1. 33 18
      background.js
  2. 27 1
      content.js
  3. 3 2
      manifest.json
  4. 273 204
      page.js

+ 33 - 18
background.js

@@ -6,43 +6,58 @@ chrome.runtime.onInstalled.addListener(function () {
 let pageState = 0; // 0 - 未创建,1 - 已创建
 let pageInfo = null;
 let pageId = "";
+let tabId = "";
 chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
   if (request.action === "show_popup") {
+    tabId = sender.tab.id;
     pageInfo = request;
+    pageInfo.tabId = tabId;
     try {
-      await chrome.tabs.get(pageId)
+      await chrome.tabs.get(pageId);
     } catch {
       pageState = 0; // 说明没找到
     }
     if (pageState === 0) {
-      chrome.windows.create({
-        url: chrome.runtime.getURL("page.html"), // 指向你的弹出页面
-        type: "popup", // 设置为弹出窗口
-        width: 1000,
-        height: 750,
-        focused: true,
-        left: 100,  // 可选,窗口的左边缘
-        top: 100    // 可选,窗口的上边缘
-      }, (newTab) => {
-        pageId = newTab.tabs[0].id;
-        pageState = 1;
+      chrome.windows.create(
+        {
+          url: chrome.runtime.getURL("page.html"), // 指向你的弹出页面
+          type: "popup", // 设置为弹出窗口
+          width: 1000,
+          height: 750,
+          focused: true,
+          left: 100, // 可选,窗口的左边缘
+          top: 100, // 可选,窗口的上边缘
+        },
+        (newTab) => {
+          pageId = newTab.tabs[0].id;
+          pageState = 1;
+        }
+      );
+    } else {
+      chrome.tabs.get(pageId, (tab) => {
+        if (tab) {
+          chrome.windows.update(tab.windowId, { focused: true });
+          chrome.tabs.update(pageId, { active: true });
+          sendTabMessage(pageId, pageInfo);
+        }
       });
     }
-    else {
-      sendTabMessage(pageId, pageInfo)
-    }
   }
 });
 
 // 监听已更新的标签,以找出何时打开了 page.html
 chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
-  if (changeInfo.status === 'complete' && tab.url.includes('page.html')) {
-    sendTabMessage(tabId, pageInfo)
+  if (changeInfo.status === "complete" && tab.url.includes("page.html")) {
+    sendTabMessage(tabId, pageInfo);
   }
 });
 
 function sendTabMessage(tabId, data) {
-  chrome.tabs.sendMessage(tabId, { msgToPopup: "发送页面", data, pageState: pageState });
+  chrome.tabs.sendMessage(tabId, {
+    msgToPopup: "发送页面",
+    data,
+    pageState: pageState,
+  });
 }
 
 // // background.js

+ 27 - 1
content.js

@@ -143,7 +143,33 @@ let isOpen = false;
 function clickHandler(e) {
   // console.log(jsRequests);
   // console.log(oldTarget);
-  chrome.runtime.sendMessage({ action: "show_popup", jslist: jsRequests, targe: oldTarget.outerHTML, csslist: myComputedStyle(oldTarget) });
+  chrome.runtime.sendMessage({
+    action: "show_popup",
+    jslist: jsRequests,
+    targe: oldTarget.outerHTML,
+    csslist: myComputedStyle(oldTarget),
+    path: getParentInfo(oldTarget),
+  });
+}
+
+function getParentInfo(element) {
+  let id = [];
+  if (element === document.body) {
+    return [1];
+  } else {
+    let parentNode = element.parentNode;
+    let index = 0;
+    for (let i = 0; parentNode.childNodes.length; i++) {
+      let child = parentNode.childNodes[i];
+      if (child.nodeName === "#text") continue;
+      if (child === element) {
+        id = [index];
+        break;
+      }
+      index++;
+    }
+    return getParentInfo(element.parentNode).concat(id);
+  }
 }
 
 // window.addEventListener("click", function (e) {

+ 3 - 2
manifest.json

@@ -9,9 +9,10 @@
     "webRequestBlocking",
     "<all_urls>",
     "activeTab",
-    "tabs"
+    "tabs",
+    "debugger"
   ],
-  "icons":{
+  "icons": {
     "16": "zlsoft.png",
     "48": "zlsoft.png",
     "128": "zlsoft.png"

+ 273 - 204
page.js

@@ -1,227 +1,296 @@
 let nowFileName = "";
-let jsonInfo = null;
-fetch('btn.json').then((s) => {
-    return s.json()
-}).then((data) => {
-    jsonInfo = data
-})
+let jsonInfo = {};
+let tabId = "";
 function InitTable() {
-    window.TabInstance = $('#filterTable').dxDataGrid({
-        dataSource: [],
-        keyExpr: 'resource_detail_id',
-        remoteOperations: false,
-        searchPanel: {
-            visible: true,
-            highlightCaseSensitive: true,
+  window.TabInstance = $("#filterTable")
+    .dxDataGrid({
+      dataSource: [],
+      keyExpr: "resource_detail_id",
+      remoteOperations: false,
+      searchPanel: {
+        visible: true,
+        highlightCaseSensitive: true,
+      },
+      groupPanel: { visible: true },
+      grouping: {
+        allowCollapsing: true,
+        autoExpandAll: true,
+        expandMode: "rowClick",
+      },
+      selection: {
+        mode: "single",
+      },
+      allowColumnReordering: true,
+      rowAlternationEnabled: true,
+      showBorders: true,
+      height: "100%",
+      columns: [
+        {
+          dataField: "JS文件",
+          dataType: "JS文件",
+          groupIndex: 0,
         },
-        groupPanel: { visible: true },
-        grouping: {
-            allowCollapsing: true,
-            autoExpandAll: true,
-            expandMode: "rowClick"
+        {
+          dataField: "过滤器",
+          caption: "过滤器",
         },
-        selection: {
-            mode: 'single'
+        {
+          dataField: "选择器类型",
+          dataType: "选择器类型",
         },
-        allowColumnReordering: true,
-        rowAlternationEnabled: true,
-        showBorders: true,
-        height: '100%',
-        columns: [
-            {
-                dataField: 'JS文件',
-                dataType: 'JS文件',
-                groupIndex: 0
-            },
-            {
-                dataField: "过滤器",
-                caption: "过滤器"
-            },
-            {
-                dataField: '选择器类型',
-                dataType: '选择器类型',
-            },
-            {
-                dataField: '调用方式',
-                dataType: '调用方式',
-            },
-            {
-                dataField: '所在位置',
-                dataType: '所在位置',
-            },
-            {
-                dataField: 'DOM操作分类',
-                dataType: 'DOM操作分类',
-            }
-        ],
-        onContentReady(e) {
-
+        {
+          dataField: "调用方式",
+          dataType: "调用方式",
         },
-        onSelectionChanged: function (selectedItems) {
-            let data = selectedItems.selectedRowsData[0];
-            if (data) {
-                let ast = data.astJSON;
-                if (data.JS文件 !== nowFileName) {
-                    nowFileName = data.JS文件;
-                    let code = window.fileList.find(o => o.name === data.JS文件).code;
-                    //更改JS代码
-                    jsCode.SetCode(code);
-                    //更改ast
-                    //window.ShowASTTree(ast, document.getElementById('astJson'))
-                }
-                //jscode定位
-                let { defineNode: { iid, loc: { end, start } } } = data.source_data;
-                {
-                    //移出所有高亮
-                    jsCode.RemoveAllHighlight();
-                    //设置高亮 
-                    jsCode.CreateHighlight({ startLine: start?.line, startColumn: start?.column + 1, endLine: end?.line, endColumn: end?.column + 1 });
-                }
-                {
-                    // //ast定位
-                    // let jsonNode = document.getElementById(iid);
-                    // if (jsonNode) {
-                    //     let textNode = Array.from(jsonNode.parentNode.childNodes).find(item => item.classList.contains("node-text"));
-                    //     $("#astJson").find(".monaco-highlight").removeClass("monaco-highlight");
-
-                    //     textNode?.classList?.add("monaco-highlight");
-                    //     scrollTo(jsonNode)
-                    // }
-                }
-            }
+        {
+          dataField: "所在位置",
+          dataType: "所在位置",
+        },
+        {
+          dataField: "DOM操作分类",
+          dataType: "DOM操作分类",
+        },
+      ],
+      onContentReady(e) {},
+      onSelectionChanged: function (selectedItems) {
+        let data = selectedItems.selectedRowsData[0];
+        if (data) {
+          let ast = data.astJSON;
+          if (data.JS文件 !== nowFileName) {
+            nowFileName = data.JS文件;
+            let code = window.fileList.find((o) => o.name === data.JS文件).code;
+            //更改JS代码
+            jsCode.SetCode(code);
+            //更改ast
+            //window.ShowASTTree(ast, document.getElementById('astJson'))
+          }
+          //jscode定位
+          let {
+            defineNode: {
+              iid,
+              loc: { end, start },
+            },
+          } = data.source_data;
+          {
+            //移出所有高亮
+            jsCode.RemoveAllHighlight();
+            //设置高亮
+            jsCode.CreateHighlight({
+              startLine: start?.line,
+              startColumn: start?.column + 1,
+              endLine: end?.line,
+              endColumn: end?.column + 1,
+            });
+          }
+          {
+            // //ast定位
+            // let jsonNode = document.getElementById(iid);
+            // if (jsonNode) {
+            //     let textNode = Array.from(jsonNode.parentNode.childNodes).find(item => item.classList.contains("node-text"));
+            //     $("#astJson").find(".monaco-highlight").removeClass("monaco-highlight");
+            //     textNode?.classList?.add("monaco-highlight");
+            //     scrollTo(jsonNode)
+            // }
+          }
         }
-    }).dxDataGrid("instance");
+      },
+    })
+    .dxDataGrid("instance");
 
-    window.CSSTabInstance = $('#cssJson').dxDataGrid({
-        dataSource: [],
-        keyExpr: 'id',
-        remoteOperations: false,
-        searchPanel: {
-            visible: true,
-            highlightCaseSensitive: true,
-        },
-        selection: {
-            mode: 'single'
+  window.CSSTabInstance = $("#cssJson")
+    .dxDataGrid({
+      dataSource: [],
+      keyExpr: "id",
+      remoteOperations: false,
+      searchPanel: {
+        visible: true,
+        highlightCaseSensitive: true,
+      },
+      selection: {
+        mode: "single",
+      },
+      allowColumnReordering: true,
+      rowAlternationEnabled: true,
+      showBorders: true,
+      height: "100%",
+      paging: {
+        enabled: false,
+        pageSize: 0,
+      },
+      columns: [
+        {
+          dataField: "key",
+          caption: "名称",
         },
-        allowColumnReordering: true,
-        rowAlternationEnabled: true,
-        showBorders: true,
-        height: '100%',
-        paging: {
-            enabled: false,
-            pageSize: 0
+        {
+          dataField: "value",
+          caption: "生效值",
         },
-        columns: [
-            {
-                dataField: "key",
-                caption: "名称"
-            },
-            {
-                dataField: 'value',
-                caption: '生效值',
-            }
-        ],
-        onSelectionChanged: function (selectedItems) {
-            let data = selectedItems.selectedRowsData[0];
-            if (data) {
-                CSSBelongInstance.option({
-                    "dataSource": findPropRef(data.key, jsonInfo).map((s, i) => ({ ...s, id: i }))
-                })
-            }
+      ],
+      onSelectionChanged: function (selectedItems) {
+        let data = selectedItems.selectedRowsData[0];
+        if (data) {
+          CSSBelongInstance.option({
+            dataSource: findPropRef(data.key, jsonInfo).map((s, i) => ({
+              ...s,
+              id: i,
+            })),
+          });
         }
-    }).dxDataGrid("instance");
+      },
+    })
+    .dxDataGrid("instance");
 
-    window.CSSBelongInstance = $('#cssBelong').dxDataGrid({
-        dataSource: [],
-        keyExpr: 'id',
-        remoteOperations: false,
-        searchPanel: {
-            visible: true,
-            highlightCaseSensitive: true,
+  window.CSSBelongInstance = $("#cssBelong")
+    .dxDataGrid({
+      dataSource: [],
+      keyExpr: "id",
+      remoteOperations: false,
+      searchPanel: {
+        visible: true,
+        highlightCaseSensitive: true,
+      },
+      selection: {
+        mode: "single",
+      },
+      allowColumnReordering: true,
+      rowAlternationEnabled: true,
+      showBorders: true,
+      paging: {
+        enabled: false,
+        pageSize: 0,
+      },
+      height: "100%",
+      columns: [
+        {
+          dataField: "来源",
+          caption: "来源",
+          width: 100,
         },
-        selection: {
-            mode: 'single'
+        {
+          dataField: "选择器",
+          caption: "选择器",
         },
-        allowColumnReordering: true,
-        rowAlternationEnabled: true,
-        showBorders: true,
-        paging: {
-            enabled: false,
-            pageSize: 0
+        {
+          dataField: "属性值",
+          caption: "属性值",
         },
-        height: '100%',
-        columns: [
-            {
-                dataField: "来源",
-                caption: "来源",
-                width: 100
-            },
-            {
-                dataField: '选择器',
-                caption: '选择器',
-            },
-            {
-                dataField: '属性值',
-                caption: '属性值',
-            }
-        ]
-    }).dxDataGrid("instance");
+      ],
+    })
+    .dxDataGrid("instance");
 }
-chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
-    if (request.msgToPopup === "发送页面") {
-        //初始化JS代码编辑器
-        window.jsCode = new CodeEditor();
-        jsCode.InitEditor($('#jscode')[0], false, false, [], false);
-        jsCode.dataType = 3;
-        InitTable();
-        let ret = request.data;
-        console.log(ret);
-        let { jslist, targe, csslist } = ret;
-        parseCodeToAST(jslist.map(item => {
-            return {
-                code: item.data,
-                name: item.fileName
-            };
-        }))
+chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
+  if (request.msgToPopup === "发送页面") {
+    //初始化JS代码编辑器
+    window.jsCode = new CodeEditor();
+    jsCode.InitEditor($("#jscode")[0], false, false, [], false);
+    jsCode.dataType = 3;
+    InitTable();
+    let ret = request.data;
+    console.log(ret);
+    let { jslist, targe, csslist, tabId: _tabId, path } = ret;
+    tabId = _tabId;
+    parseCodeToAST(
+      jslist.map((item) => {
+        return {
+          code: item.data,
+          name: item.fileName,
+        };
+      })
+    );
 
-        let data = window.findSelector();
-        let id = $(targe).attr('id');
-        let classList = $(targe).attr('class').split(' ');
-        data = data.filter(m => {
-            let v = m.过滤器;
-            if (v.includes(id)) return true;
+    let data = window.findSelector();
+    let id = $(targe).attr("id");
+    let classList = $(targe).attr("class").split(" ");
+    data = data.filter((m) => {
+      let v = m.过滤器;
+      if (v.includes(id)) return true;
 
-            if (classList.length > 0) {
-                for (const classitem of classList) {
-                    if (v.includes(classitem)) return true;
-                }
-            }
-        });
+      if (classList.length > 0) {
+        for (const classitem of classList) {
+          if (v.includes(classitem)) return true;
+        }
+      }
+    });
 
-        TabInstance.option({
-            "dataSource": data
-        });
+    await attach();
+    await getPathNodeInfo(path);
+    TabInstance.option({
+      dataSource: data,
+    });
 
-        CSSTabInstance.option({
-            "dataSource": Object.entries(csslist).map((a, index) => ({ id: index, key: a[0], value: a[1] }))
-        })
-    }
-})
+    CSSTabInstance.option({
+      dataSource: Object.entries(csslist).map((a, index) => ({
+        id: index,
+        key: a[0],
+        value: a[1],
+      })),
+    });
+  }
+});
 
 function findPropRef(key, json) {
-    let matchedCSSRules = json.matchedCSSRules;
-    let retArr = [];
-    for (const matchedCSSRule of matchedCSSRules) {
-        let cssProperties = matchedCSSRule.rule.style.cssProperties;
-        let cssProp = cssProperties.find((m) => m.name == key);
-        if (!cssProp) continue;
-        let ret = {
-            来源: "CSS",
-            选择器: matchedCSSRule.rule.selectorList.text,
-            选中选择器: matchedCSSRule.matchingSelectors[0],
-            属性值: cssProp.value,
-        };
-        retArr.push(ret);
+  let matchedCSSRules = json.matchedCSSRules;
+  let retArr = [];
+  for (const matchedCSSRule of matchedCSSRules) {
+    let cssProperties = matchedCSSRule.rule.style.cssProperties;
+    let cssProp = cssProperties.find((m) => m.name == key);
+    if (!cssProp) continue;
+    let ret = {
+      来源: "CSS",
+      选择器: matchedCSSRule.rule.selectorList.text,
+      选中选择器: matchedCSSRule.matchingSelectors[0],
+      属性值: cssProp.value,
+    };
+    retArr.push(ret);
+  }
+  return retArr;
+}
+
+async function getPathNodeInfo(path) {
+  const doc = await getDocument();
+  const htmlInfo = doc.children.find((m) => m.localName === "html");
+  let info = htmlInfo;
+  for (const index of path) {
+    info = getpath(info, index);
+  }
+  let nodeId = info.nodeId;
+  let cssInfo = await getMatchedStylesForNode(nodeId);
+  jsonInfo = cssInfo;
+
+  function getpath(info, index) {
+    let children = info.children;
+    return children[index];
+  }
+}
+
+async function getMatchedStylesForNode(nodeId) {
+  let ret = await chrome.debugger.sendCommand(
+    { tabId },
+    "CSS.getMatchedStylesForNode",
+    {
+      nodeId,
     }
-    return retArr;
-}
+  );
+  return ret;
+}
+
+async function getDocument() {
+  const doc = await chrome.debugger.sendCommand({ tabId }, "DOM.getDocument", {
+    pierce: true,
+    depth: -1,
+  });
+  return doc.root;
+}
+
+async function attach() {
+  const targets = await chrome.debugger.getTargets();
+  debugger;
+  let target = targets.find((m) => m.tabId == tabId);
+  if (target?.attached === true) {
+  } else {
+    await chrome.debugger.attach({ tabId }, "1.3");
+  }
+  await chrome.debugger.sendCommand({ tabId }, "DOM.enable");
+  await chrome.debugger.sendCommand({ tabId }, "CSS.enable");
+}