page.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. let nowFileName = "";
  2. let jsonInfo = {};
  3. let tabId = "";
  4. let nodeObj;
  5. let jslist;
  6. let cssList;
  7. let cssFileInfo = {}
  8. chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
  9. if (request.msgToPopup === "发送页面") {
  10. cssFileInfo = {}
  11. //初始化JS代码编辑器
  12. window.jsCode = new CodeEditor();
  13. jsCode.InitEditor($("#jscode")[0], false, false, [], false);
  14. jsCode.dataType = 3;
  15. InitTable();
  16. // 结构接收的信息
  17. let { jslist: _jslist, targe, csslist, tabId: _tabId, path } = request.data;
  18. jslist = _jslist;
  19. tabId = _tabId;
  20. cssList = csslist; // 页面的所有样式信息
  21. parseCodeToAST(
  22. jslist.map((item) => {
  23. return {
  24. code: item.data,
  25. name: item.fileName,
  26. };
  27. })
  28. );
  29. let data = window.findSelector();
  30. let id = $(targe).attr("id");
  31. let classList = $(targe).attr("class").split(" ");
  32. data = data.filter((m) => {
  33. let v = m.过滤器;
  34. if (v.includes(id)) return true;
  35. if (classList.length > 0) {
  36. for (const classitem of classList) {
  37. if (v.includes(classitem)) return true;
  38. }
  39. }
  40. });
  41. await attach();
  42. await getPathNodeInfo(path);
  43. let events = await findEvent();
  44. TabInstance.option({
  45. dataSource: data,
  46. });
  47. let cssJsonData = CssJsonData(jsonInfo)
  48. CSSTabInstance.option({
  49. dataSource: cssJsonData,
  50. });
  51. eventTableInstance.option({
  52. dataSource: translateEventData(events),
  53. });
  54. }
  55. });
  56. function InitTable() {
  57. window.TabInstance = $("#filterTable")
  58. .dxDataGrid({
  59. dataSource: [],
  60. keyExpr: "resource_detail_id",
  61. remoteOperations: false,
  62. searchPanel: {
  63. visible: true,
  64. highlightCaseSensitive: true,
  65. },
  66. groupPanel: { visible: true },
  67. grouping: {
  68. allowCollapsing: true,
  69. autoExpandAll: true,
  70. expandMode: "rowClick",
  71. },
  72. selection: {
  73. mode: "single",
  74. },
  75. allowColumnReordering: true,
  76. rowAlternationEnabled: true,
  77. showBorders: true,
  78. height: "100%",
  79. columns: [
  80. {
  81. dataField: "JS文件",
  82. dataType: "JS文件",
  83. groupIndex: 0,
  84. },
  85. {
  86. dataField: "过滤器",
  87. caption: "过滤器",
  88. },
  89. {
  90. dataField: "选择器类型",
  91. dataType: "选择器类型",
  92. },
  93. {
  94. dataField: "调用方式",
  95. dataType: "调用方式",
  96. },
  97. {
  98. dataField: "所在位置",
  99. dataType: "所在位置",
  100. },
  101. {
  102. dataField: "DOM操作分类",
  103. dataType: "DOM操作分类",
  104. },
  105. ],
  106. onContentReady(e) { },
  107. onSelectionChanged: function (selectedItems) {
  108. let data = selectedItems.selectedRowsData[0];
  109. jsCode.dataType = 3;
  110. if (data) {
  111. let ast = data.astJSON;
  112. if (data.JS文件 !== nowFileName) {
  113. nowFileName = data.JS文件;
  114. let code = window.fileList.find((o) => o.name === data.JS文件).code;
  115. //更改JS代码
  116. jsCode.SetCode(code);
  117. }
  118. //jscode定位
  119. let {
  120. defineNode: {
  121. iid,
  122. loc: { end, start },
  123. },
  124. } = data.source_data;
  125. {
  126. //移出所有高亮
  127. jsCode.RemoveAllHighlight();
  128. //设置高亮
  129. jsCode.CreateHighlight({
  130. startLine: start?.line,
  131. startColumn: start?.column + 1,
  132. endLine: end?.line,
  133. endColumn: end?.column + 1,
  134. });
  135. }
  136. }
  137. },
  138. })
  139. .dxDataGrid("instance");
  140. window.CSSTabInstance = $("#cssJson")
  141. .dxDataGrid({
  142. dataSource: [],
  143. keyExpr: "id",
  144. remoteOperations: false,
  145. searchPanel: {
  146. visible: true,
  147. highlightCaseSensitive: true,
  148. },
  149. selection: {
  150. mode: "single",
  151. },
  152. groupPanel: { visible: true },
  153. grouping: {
  154. allowCollapsing: true,
  155. autoExpandAll: true,
  156. expandMode: "rowClick",
  157. },
  158. allowColumnReordering: true,
  159. rowAlternationEnabled: true,
  160. showBorders: true,
  161. height: "100%",
  162. paging: {
  163. enabled: false,
  164. pageSize: 0,
  165. },
  166. columns: [
  167. {
  168. dataField: "文件",
  169. caption: "来源文件",
  170. cellTemplate: function (tdom, tdMsg) {
  171. let name = tdMsg.value;
  172. tdom.text(name === "用户自定义" ? name : name.match(/\/([^\/?]+)(?:\?[^\s]*)?$/)[1])
  173. }
  174. },
  175. {
  176. dataField: "选择器",
  177. caption: "选择器"
  178. },
  179. {
  180. dataField: "分类",
  181. caption: "分类",
  182. groupIndex: 0
  183. }, {
  184. dataField: "样式属性",
  185. caption: "样式属性",
  186. cellTemplate: function (tdom, tdMsg) {
  187. let styles = tdMsg.value;
  188. let html = styles.map(({ name, value }) => `<li>${name}: ${value}</li>`).join('')
  189. tdom.html(`<ul>${html}</ul>`)
  190. }
  191. },
  192. ],
  193. onSelectionChanged: async function (selectedItems) {
  194. let data = selectedItems.selectedRowsData[0];
  195. jsCode.dataType = 1;
  196. if (data) {
  197. if (data.文件) {
  198. let fileName = data.文件;
  199. let code = ""
  200. if (!cssFileInfo[fileName]) {
  201. code = fileName === "用户自定义" ? "" : await (await fetch(fileName)).text();
  202. } else {
  203. code = !cssFileInfo[fileName]
  204. }
  205. cssFileInfo[fileName] = code
  206. //更改JS代码
  207. jsCode.SetCode(code);
  208. }
  209. }
  210. },
  211. })
  212. .dxDataGrid("instance");
  213. window.eventTableInstance = $("#eventTable")
  214. .dxDataGrid({
  215. dataSource: [],
  216. keyExpr: "id",
  217. remoteOperations: false,
  218. searchPanel: {
  219. visible: true,
  220. highlightCaseSensitive: true,
  221. },
  222. selection: {
  223. mode: "single",
  224. },
  225. allowColumnReordering: true,
  226. rowAlternationEnabled: true,
  227. showBorders: true,
  228. paging: {
  229. enabled: false,
  230. pageSize: 0,
  231. },
  232. height: "100%",
  233. columns: [
  234. {
  235. dataField: "事件名称",
  236. caption: "事件名称",
  237. },
  238. {
  239. dataField: "绑定对象",
  240. caption: "绑定对象",
  241. },
  242. {
  243. dataField: "事件文件",
  244. caption: "事件文件",
  245. },
  246. ],
  247. })
  248. .dxDataGrid("instance");
  249. }
  250. function findPropRef(key, json) {
  251. let matchedCSSRules = json.matchedCSSRules;
  252. let retArr = [];
  253. for (const matchedCSSRule of matchedCSSRules) {
  254. let cssProperties = matchedCSSRule.rule.style.cssProperties;
  255. let cssProp = cssProperties.find((m) => m.name == key);
  256. if (!cssProp) continue;
  257. let ret = {
  258. 来源: "CSS",
  259. 选择器: matchedCSSRule.rule.selectorList.text,
  260. 选中选择器: matchedCSSRule.matchingSelectors[0],
  261. 属性值: cssProp.value,
  262. };
  263. retArr.push(ret);
  264. }
  265. return retArr;
  266. }
  267. async function getPathNodeInfo(path) {
  268. const doc = await getDocument();
  269. // const htmlInfo = doc.children.find((m) => m.localName === "html");
  270. let info = doc;
  271. for (const index of path) {
  272. info = getpath(info, index);
  273. }
  274. nodeObj = info;
  275. let nodeId = info.nodeId;
  276. let cssInfo = await getMatchedStylesForNode(nodeId);
  277. jsonInfo = cssInfo;
  278. function getpath(info, index) {
  279. let children = info.children;
  280. return children[index];
  281. }
  282. }
  283. async function getMatchedStylesForNode(nodeId) {
  284. let ret = await chrome.debugger.sendCommand(
  285. { tabId },
  286. "CSS.getMatchedStylesForNode",
  287. {
  288. nodeId,
  289. }
  290. );
  291. return ret;
  292. }
  293. async function getDocument() {
  294. const doc = await chrome.debugger.sendCommand({ tabId }, "DOM.getDocument", {
  295. pierce: true,
  296. depth: -1,
  297. });
  298. return doc.root;
  299. }
  300. async function attach() {
  301. // const targets = await chrome.debugger.getTargets();
  302. // let target = targets.find((m) => m.tabId == tabId);
  303. // if (target?.attached === true) {
  304. // } else {
  305. // await chrome.debugger.attach({ tabId }, "1.3");
  306. // }
  307. await chrome.debugger.attach({ tabId }, "1.3").catch(() => { });
  308. await chrome.debugger.sendCommand({ tabId }, "DOM.enable");
  309. await chrome.debugger.sendCommand({ tabId }, "CSS.enable");
  310. await chrome.debugger.sendCommand({ tabId }, "Debugger.enable");
  311. }
  312. async function findEvent() {
  313. let winObj = await chrome.debugger.sendCommand(
  314. { tabId },
  315. "Runtime.evaluate",
  316. {
  317. expression: "self",
  318. objectGroup: "",
  319. includeCommandLineAPI: false,
  320. silent: true,
  321. returnByValue: false,
  322. generatePreview: false,
  323. userGesture: false,
  324. awaitPromise: false,
  325. }
  326. );
  327. let winEvents = await chrome.debugger.sendCommand(
  328. { tabId },
  329. "DOMDebugger.getEventListeners",
  330. {
  331. objectId: winObj.result.objectId,
  332. }
  333. );
  334. let documentObj = await chrome.debugger.sendCommand(
  335. { tabId },
  336. "Runtime.evaluate",
  337. {
  338. expression: "document",
  339. objectGroup: "",
  340. includeCommandLineAPI: false,
  341. silent: true,
  342. returnByValue: false,
  343. generatePreview: false,
  344. userGesture: false,
  345. awaitPromise: false,
  346. }
  347. );
  348. let documentEvents = await chrome.debugger.sendCommand(
  349. { tabId },
  350. "DOMDebugger.getEventListeners",
  351. {
  352. objectId: documentObj.result.objectId,
  353. }
  354. );
  355. let selfObj = await chrome.debugger.sendCommand(
  356. { tabId },
  357. "DOM.resolveNode",
  358. {
  359. nodeId: nodeObj.nodeId,
  360. }
  361. );
  362. let selfEvents = await chrome.debugger.sendCommand(
  363. { tabId },
  364. "DOMDebugger.getEventListeners",
  365. {
  366. objectId: selfObj.object.objectId,
  367. }
  368. );
  369. for (const listener of winEvents.listeners) {
  370. await listenerGetFile(listener);
  371. }
  372. for (const listener of documentEvents.listeners) {
  373. await listenerGetFile(listener);
  374. }
  375. for (const listener of selfEvents.listeners) {
  376. await listenerGetFile(listener);
  377. }
  378. return {
  379. winEvents: winEvents.listeners,
  380. documentEvents: documentEvents.listeners,
  381. selfEvents: selfEvents.listeners,
  382. };
  383. }
  384. async function listenerGetFile(listener) {
  385. let ret = await chrome.debugger.sendCommand(
  386. { tabId },
  387. "Debugger.getScriptSource",
  388. {
  389. scriptId: listener.scriptId,
  390. }
  391. );
  392. let js = jslist.find((m) => m.data == ret.scriptSource);
  393. if (js) {
  394. js.scriptId = listener.scriptId;
  395. listener.fileName = js.fileName;
  396. listener.fileUrl = js.url;
  397. listener.fileData = js.data;
  398. }
  399. }
  400. function translateEventData(eventObj) {
  401. let { winEvents, documentEvents, selfEvents } = eventObj;
  402. let result = [];
  403. result.push(
  404. ...winEvents.map((even) => ({
  405. 事件名称: even.type,
  406. 绑定对象: "window",
  407. 事件文件: even.fileName,
  408. }))
  409. );
  410. result.push(
  411. ...documentEvents.map((even) => ({
  412. 事件名称: even.type,
  413. 绑定对象: "document",
  414. 事件文件: even.fileName,
  415. }))
  416. );
  417. result.push(
  418. ...selfEvents.map((even) => ({
  419. 事件名称: even.type,
  420. 绑定对象: "selft",
  421. 事件文件: even.fileName,
  422. }))
  423. );
  424. return result.map((a, index) => ({ ...a, id: index }));
  425. }
  426. window.onload = function () {
  427. InitTabOperation();
  428. };
  429. /**
  430. * 设置操作页卡功能
  431. */
  432. function InitTabOperation() {
  433. document.querySelector(".tabs").addEventListener("click", function (e) {
  434. let target = e.target;
  435. if (target.classList.contains("tab")) {
  436. showContent(target);
  437. }
  438. });
  439. }
  440. function showContent(tab) {
  441. let id = tab.dataset.id; // 获取点击的页卡ID
  442. // 获取选中的页卡元素
  443. let activeTab = document.querySelector(".tabs .active");
  444. if (activeTab !== null) {
  445. if (id === activeTab.dataset.id) return;
  446. activeTab.classList.remove("active");
  447. }
  448. // 获取选中的容器的元素
  449. let activeContent = document.querySelector(".tab-container .active");
  450. if (activeContent !== null) {
  451. if (activeContent.id === id) return;
  452. activeContent.classList.remove("active");
  453. }
  454. // 给新选中的页卡加入选中效果
  455. tab.classList.add("active");
  456. let curActiveContent = document.querySelector(`.tab-container #${id}`);
  457. if (curActiveContent !== null) {
  458. curActiveContent.classList.add("active");
  459. }
  460. }
  461. /**
  462. * 接收转换后有用的json数据
  463. * @param {} jsonData
  464. */
  465. function CssJsonData(jsonData) {
  466. let data = CssJsonRules.parseJson(jsonData);
  467. let { 伪类的样式, 内敛的样式, 匹配的样式, 继承的样式 } = data;
  468. let result = [];
  469. 伪类的样式.forEach((rule) => {
  470. let { matchs, pseudoType } = rule;
  471. matchs.forEach(match => {
  472. result.push({
  473. 文件: match.origin,
  474. 样式属性: match.style,
  475. 选择器: match.text,
  476. 分类: "伪类::" + pseudoType + "样式"
  477. })
  478. })
  479. });
  480. if (内敛的样式.length > 0) {
  481. result.push({
  482. 文件: "",
  483. 样式属性: 内敛的样式,
  484. 选择器: "",
  485. 分类: "内敛样式"
  486. })
  487. }
  488. 匹配的样式.forEach((rule) => {
  489. result.push({
  490. 文件: rule.origin,
  491. 样式属性: rule.style,
  492. 选择器: rule.text,
  493. 分类: "匹配样式"
  494. })
  495. })
  496. 继承的样式.forEach((rule) => {
  497. result.push({
  498. 文件: rule.origin,
  499. 样式属性: rule.style,
  500. 选择器: rule.text,
  501. 分类: "继承样式"
  502. })
  503. })
  504. return result.map((a, index) => ({ ...a, id: index }));
  505. }
  506. /**
  507. * css基础权重规则
  508. */
  509. class CSSSRule {
  510. static calculateSpecificity(selector) {
  511. // 初始化权重
  512. let ids = 0;
  513. let classes = 0;
  514. let tags = 0;
  515. // 去掉多余的空格
  516. const parts = selector.trim().split(/\s+/);
  517. parts.forEach(part => {
  518. // 检查每个选择器部分
  519. if (part.startsWith('#')) {
  520. ids += 1; // ID选择器
  521. } else if (part.startsWith('.')) {
  522. classes += 1; // 类选择器
  523. } else {
  524. tags += 1; // 标签选择器
  525. }
  526. });
  527. // 返回权重对象
  528. // 计算最终权重值
  529. const specificityValue = (ids * 100) + (classes * 10) + tags;
  530. return specificityValue;
  531. }
  532. static cacheStyle = {}
  533. static getStyleHref(styleId, selectorText) {
  534. if (CSSSRule.cacheStyle[styleId]) return CSSSRule.cacheStyle[styleId];
  535. foo: for (let sheet of cssList) {
  536. try {
  537. let { href, selectorTexts } = sheet;
  538. for (let text of selectorTexts)
  539. if (selectorText === text) {
  540. CSSSRule.cacheStyle[styleId] = href;
  541. break foo;
  542. }
  543. } catch { }
  544. }
  545. return CSSSRule.cacheStyle[styleId]
  546. }
  547. // css属性扩展
  548. static cssExtent = [
  549. {
  550. "property": "margin",
  551. "sub-properties": [
  552. "margin-top",
  553. "margin-right",
  554. "margin-bottom",
  555. "margin-left"
  556. ]
  557. },
  558. {
  559. "property": "padding",
  560. "sub-properties": [
  561. "padding-top",
  562. "padding-right",
  563. "padding-bottom",
  564. "padding-left"
  565. ]
  566. },
  567. {
  568. "property": "border",
  569. "sub-properties": [
  570. "border-width",
  571. "border-style",
  572. "border-color",
  573. "border-top",
  574. "border-right",
  575. "border-bottom",
  576. "border-left"
  577. ]
  578. },
  579. {
  580. "property": "border-style",
  581. "sub-properties": [
  582. "border-top-style",
  583. "border-right-style",
  584. "border-bottom-style",
  585. "border-left-style"
  586. ]
  587. },
  588. {
  589. "property": "border-top",
  590. "sub-properties": [
  591. "border-top-width",
  592. "border-top-style",
  593. "border-top-color"
  594. ]
  595. },
  596. {
  597. "property": "border-bottom",
  598. "sub-properties": [
  599. "border-bottom-width",
  600. "border-bottom-style",
  601. "border-bottom-color"
  602. ]
  603. },
  604. {
  605. "property": "border-left",
  606. "sub-properties": [
  607. "border-left-width",
  608. "border-left-style",
  609. "border-left-color"
  610. ]
  611. },
  612. {
  613. "property": "border-right",
  614. "sub-properties": [
  615. "border-right-width",
  616. "border-right-style",
  617. "border-right-color"
  618. ]
  619. },
  620. {
  621. "property": "border-radius",
  622. "sub-properties": [
  623. "border-top-left-radius",
  624. "border-top-right-radius",
  625. "border-bottom-right-radius",
  626. "border-bottom-left-radius"
  627. ]
  628. },
  629. {
  630. "property": "background",
  631. "sub-properties": [
  632. "background-color",
  633. "background-image",
  634. "background-repeat",
  635. "background-position",
  636. "background-size",
  637. "background-attachment",
  638. "background-clip",
  639. "background-origin"
  640. ]
  641. },
  642. {
  643. "property": "font",
  644. "sub-properties": [
  645. "font-style",
  646. "font-variant",
  647. "font-weight",
  648. "font-size",
  649. "line-height",
  650. "font-family"
  651. ]
  652. },
  653. {
  654. "property": "list-style",
  655. "sub-properties": [
  656. "list-style-type",
  657. "list-style-position",
  658. "list-style-image"
  659. ]
  660. },
  661. {
  662. "property": "text-decoration",
  663. "sub-properties": [
  664. "text-decoration-line",
  665. "text-decoration-color",
  666. "text-decoration-style",
  667. "text-decoration-thickness"
  668. ]
  669. },
  670. {
  671. "property": "transition",
  672. "sub-properties": [
  673. "transition-property",
  674. "transition-duration",
  675. "transition-timing-function",
  676. "transition-delay"
  677. ]
  678. },
  679. {
  680. "property": "animation",
  681. "sub-properties": [
  682. "animation-name",
  683. "animation-duration",
  684. "animation-timing-function",
  685. "animation-delay",
  686. "animation-iteration-count",
  687. "animation-direction",
  688. "animation-fill-mode",
  689. "animation-play-state"
  690. ]
  691. },
  692. {
  693. "property": "grid",
  694. "sub-properties": [
  695. "grid-template-rows",
  696. "grid-template-columns",
  697. "grid-template-areas",
  698. "grid-area",
  699. "grid-column",
  700. "grid-row",
  701. "grid-auto-rows",
  702. "grid-auto-columns",
  703. "grid-auto-flow"
  704. ]
  705. },
  706. {
  707. "property": "flex",
  708. "sub-properties": [
  709. "flex-grow",
  710. "flex-shrink",
  711. "flex-basis"
  712. ]
  713. },
  714. {
  715. "property": "outline",
  716. "sub-properties": [
  717. "outline-width",
  718. "outline-style",
  719. "outline-color"
  720. ]
  721. }
  722. ]
  723. }
  724. /**
  725. * 根据json导出数据
  726. */
  727. class CssJsonRules {
  728. static findExtentInfo(entries) {
  729. return entries.map(e => {
  730. let extentInfo = CSSSRule.cssExtent.find(a => a.property === e.name);
  731. if (extentInfo) {
  732. return extentInfo["sub-properties"];
  733. }
  734. return undefined
  735. }).filter(Boolean).flat();
  736. }
  737. /**
  738. * 解析json数据
  739. * @param {*} jsonData
  740. * @returns
  741. */
  742. static parseJson(jsonData) {
  743. let { inlineStyle, matchedCSSRules, pseudoElements, inherited } = jsonData;
  744. let result = {
  745. "内敛的样式": [],
  746. "匹配的样式": [],
  747. "伪类的样式": [],
  748. "继承的样式": []
  749. }
  750. // 解析json中的内敛样式
  751. result.内敛的样式.push(...inlineStyle.cssProperties.filter(a => a.text !== undefined).map(({ name, value }) => ({ name, value })));
  752. // 解析json中的匹配样式
  753. matchedCSSRules.forEach(cssRule => {
  754. let { rule } = cssRule;
  755. let { shorthandEntries } = rule;
  756. // 按照规律查询出信息
  757. let style = rule.style.cssProperties.filter(a => a.text !== undefined || rule.origin === "user-agent").map(({ name, value }) => ({ name, value }));
  758. if (rule.origin === "user-agent" && shorthandEntries && shorthandEntries.length > 0) {
  759. let sameInfo = CssJsonRules.findExtentInfo(shorthandEntries);
  760. style = style.filter(s => !sameInfo.includes(s.name))
  761. }
  762. let obj = {
  763. origin: rule.styleSheetId ? CSSSRule.getStyleHref(rule.styleSheetId, rule.selectorList.text) : '用户自定义',
  764. text: rule.selectorList.text,
  765. style
  766. };
  767. result.匹配的样式.push(obj)
  768. })
  769. // 解析伪类的样式
  770. pseudoElements.forEach(cssRule => {
  771. let { pseudoType, matches } = cssRule;
  772. let obj = {
  773. pseudoType,
  774. matchs: matches.map(({ rule }) => ({
  775. origin: rule.styleSheetId ? CSSSRule.getStyleHref(rule.styleSheetId, rule.selectorList.text) : '用户自定义',
  776. text: rule.selectorList.text,
  777. style: rule.style.cssProperties.filter(a => a.text !== undefined).map(({ name, value }) => ({ name, value }))
  778. }))
  779. };
  780. result.伪类的样式.push(obj)
  781. })
  782. // 解析继承的样式
  783. inherited.forEach(inheritedCssRule => {
  784. let matchedCSSRules = inheritedCssRule.matchedCSSRules;
  785. matchedCSSRules.forEach((cssRule) => {
  786. let { rule } = cssRule;
  787. let style = rule.style.cssProperties.filter(a => a.text !== undefined).map(({ name, value }) => ({ name, value }));
  788. if (style.length === 0) return;
  789. result.继承的样式.push({
  790. origin: rule.styleSheetId ? CSSSRule.getStyleHref(rule.styleSheetId, rule.selectorList.text) : '用户自定义',
  791. text: rule.selectorList.text,
  792. style
  793. })
  794. })
  795. })
  796. return result;
  797. }
  798. }