soiz1 commited on
Commit
b3de035
·
verified ·
1 Parent(s): f29a6e1

Update dev-tools.js

Browse files
Files changed (1) hide show
  1. dev-tools.js +110 -48
dev-tools.js CHANGED
@@ -15,6 +15,7 @@
15
  };
16
  let observer = null;
17
  let refreshElementsPanel = null;
 
18
 
19
  // Web Vitalsスクリプトを動的に読み込み
20
  const loadWebVitals = () => {
@@ -31,7 +32,30 @@
31
  });
32
  };
33
 
34
- // スタイルの動的追加 (ダークテーマ)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  const style = document.createElement('style');
36
  style.textContent = `
37
  :root {
@@ -578,32 +602,6 @@
578
  }
579
  `;
580
  document.head.appendChild(style);
581
-
582
- // DOM変更を監視するMutationObserver
583
- const setupMutationObserver = () => {
584
- observer = new MutationObserver((mutations) => {
585
- mutations.forEach((mutation) => {
586
- if (mutation.type === 'childList') {
587
- mutation.addedNodes.forEach((node) => {
588
- if (node.nodeType === Node.ELEMENT_NODE) {
589
- highlightNode(node);
590
- }
591
- });
592
- }
593
- });
594
- if (refreshElementsPanel) {
595
- refreshElementsPanel();
596
- }
597
- });
598
-
599
- observer.observe(document.documentElement, {
600
- childList: true,
601
- subtree: true,
602
- attributes: true,
603
- characterData: true
604
- });
605
- };
606
-
607
  // ノードをハイライト表示
608
  function highlightNode(node) {
609
  const elementId = node.id || Math.random().toString(36).substr(2, 9);
@@ -709,6 +707,13 @@
709
  container.className = 'vitals-container';
710
  panel.appendChild(container);
711
 
 
 
 
 
 
 
 
712
  // CLS (Cumulative Layout Shift)
713
  const clsCard = document.createElement('div');
714
  clsCard.className = 'vital-card';
@@ -779,29 +784,34 @@
779
  `;
780
  container.appendChild(ttfbCard);
781
 
782
- // Web Vitalsの計測を開始
783
- loadWebVitals().then(() => {
784
- if (window.webVitals) {
785
- try {
786
- const vitals = window.webVitals;
787
- if (vitals.getCLS) {
788
- vitals.getCLS(updateCLS);
789
- vitals.getFCP(updateFCP);
790
- vitals.getFID(updateFID);
791
- vitals.getLCP(updateLCP);
792
- vitals.getTTFB(updateTTFB);
793
- } else if (vitals.onCLS) {
794
- vitals.onCLS(updateCLS);
795
- vitals.onFCP(updateFCP);
796
- vitals.onFID(updateFID);
797
- vitals.onLCP(updateLCP);
798
- vitals.onTTFB(updateTTFB);
 
 
 
 
 
 
 
799
  }
800
- } catch (e) {
801
- console.error('Web Vitals error:', e);
802
  }
803
- }
804
- });
805
 
806
  function updateCLS(metric) {
807
  vitalsData.CLS = metric.value;
@@ -1216,6 +1226,7 @@
1216
  contextMenu.className = 'context-menu';
1217
  contextMenu.innerHTML = `
1218
  <div class="context-menu-item" data-action="edit-html">HTMLとして編集</div>
 
1219
  <div class="context-menu-item" data-action="add-attribute">属性を追加</div>
1220
  <div class="context-menu-item" data-action="edit-element">要素を編集</div>
1221
  <div class="context-menu-item" data-action="duplicate">要素を複製</div>
@@ -1488,6 +1499,57 @@
1488
  }
1489
  });
1490
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1491
  case 'add-attribute':
1492
  const attrName = prompt('属性名を入力');
1493
  if (attrName) {
 
15
  };
16
  let observer = null;
17
  let refreshElementsPanel = null;
18
+ let vitalsMeasurementStarted = false;
19
 
20
  // Web Vitalsスクリプトを動的に読み込み
21
  const loadWebVitals = () => {
 
32
  });
33
  };
34
 
35
+ // DOM変更を監視するMutationObserver
36
+ const setupMutationObserver = () => {
37
+ observer = new MutationObserver((mutations) => {
38
+ mutations.forEach((mutation) => {
39
+ if (mutation.type === 'childList') {
40
+ mutation.addedNodes.forEach((node) => {
41
+ if (node.nodeType === Node.ELEMENT_NODE) {
42
+ highlightNode(node);
43
+ }
44
+ });
45
+ }
46
+ });
47
+ if (refreshElementsPanel) {
48
+ refreshElementsPanel();
49
+ }
50
+ });
51
+
52
+ observer.observe(document.documentElement, {
53
+ childList: true,
54
+ subtree: true,
55
+ attributes: true,
56
+ characterData: true
57
+ });
58
+ };
59
  const style = document.createElement('style');
60
  style.textContent = `
61
  :root {
 
602
  }
603
  `;
604
  document.head.appendChild(style);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
605
  // ノードをハイライト表示
606
  function highlightNode(node) {
607
  const elementId = node.id || Math.random().toString(36).substr(2, 9);
 
707
  container.className = 'vitals-container';
708
  panel.appendChild(container);
709
 
710
+ // 測定開始ボタン
711
+ const startButton = document.createElement('button');
712
+ startButton.className = 'add-btn';
713
+ startButton.textContent = '測定を開始';
714
+ startButton.onclick = startVitalsMeasurement;
715
+ container.appendChild(startButton);
716
+
717
  // CLS (Cumulative Layout Shift)
718
  const clsCard = document.createElement('div');
719
  clsCard.className = 'vital-card';
 
784
  `;
785
  container.appendChild(ttfbCard);
786
 
787
+ function startVitalsMeasurement() {
788
+ if (vitalsMeasurementStarted) return;
789
+ vitalsMeasurementStarted = true;
790
+
791
+ loadWebVitals().then(() => {
792
+ if (window.webVitals) {
793
+ try {
794
+ const vitals = window.webVitals;
795
+ if (vitals.getCLS) {
796
+ vitals.getCLS(updateCLS);
797
+ vitals.getFCP(updateFCP);
798
+ vitals.getFID(updateFID);
799
+ vitals.getLCP(updateLCP);
800
+ vitals.getTTFB(updateTTFB);
801
+ } else if (vitals.onCLS) {
802
+ vitals.onCLS(updateCLS);
803
+ vitals.onFCP(updateFCP);
804
+ vitals.onFID(updateFID);
805
+ vitals.onLCP(updateLCP);
806
+ vitals.onTTFB(updateTTFB);
807
+ }
808
+ alert('Web Vitalsの測定を開始しました');
809
+ } catch (e) {
810
+ console.error('Web Vitals error:', e);
811
  }
 
 
812
  }
813
+ });
814
+ }
815
 
816
  function updateCLS(metric) {
817
  vitalsData.CLS = metric.value;
 
1226
  contextMenu.className = 'context-menu';
1227
  contextMenu.innerHTML = `
1228
  <div class="context-menu-item" data-action="edit-html">HTMLとして編集</div>
1229
+ <div class="context-menu-item" data-action="edit-whole-html">HTML全体を編集</div>
1230
  <div class="context-menu-item" data-action="add-attribute">属性を追加</div>
1231
  <div class="context-menu-item" data-action="edit-element">要素を編集</div>
1232
  <div class="context-menu-item" data-action="duplicate">要素を複製</div>
 
1499
  }
1500
  });
1501
  break;
1502
+ case 'edit-whole-html':
1503
+ const htmlContent = document.documentElement.outerHTML;
1504
+ const textarea = document.createElement('textarea');
1505
+ textarea.style.width = '100%';
1506
+ textarea.style.height = '300px';
1507
+ textarea.value = htmlContent;
1508
+
1509
+ const modal = document.createElement('div');
1510
+ modal.style.position = 'fixed';
1511
+ modal.style.top = '0';
1512
+ modal.style.left = '0';
1513
+ modal.style.width = '100%';
1514
+ modal.style.height = '100%';
1515
+ modal.style.backgroundColor = 'rgba(0,0,0,0.8)';
1516
+ modal.style.zIndex = '10000';
1517
+ modal.style.display = 'flex';
1518
+ modal.style.flexDirection = 'column';
1519
+ modal.style.padding = '20px';
1520
+ modal.style.boxSizing = 'border-box';
1521
+
1522
+ const buttonContainer = document.createElement('div');
1523
+ buttonContainer.style.marginTop = '10px';
1524
+ buttonContainer.style.display = 'flex';
1525
+ buttonContainer.style.gap = '10px';
1526
+
1527
+ const saveButton = document.createElement('button');
1528
+ saveButton.textContent = '保存';
1529
+ saveButton.onclick = () => {
1530
+ try {
1531
+ document.documentElement.innerHTML = textarea.value;
1532
+ modal.remove();
1533
+ refreshElementsPanel();
1534
+ } catch (e) {
1535
+ alert('HTMLの解析に失敗しました: ' + e.message);
1536
+ }
1537
+ };
1538
+
1539
+ const cancelButton = document.createElement('button');
1540
+ cancelButton.textContent = 'キャンセル';
1541
+ cancelButton.onclick = () => {
1542
+ modal.remove();
1543
+ };
1544
+
1545
+ buttonContainer.appendChild(saveButton);
1546
+ buttonContainer.appendChild(cancelButton);
1547
+
1548
+ modal.appendChild(textarea);
1549
+ modal.appendChild(buttonContainer);
1550
+
1551
+ document.body.appendChild(modal);
1552
+ break;
1553
  case 'add-attribute':
1554
  const attrName = prompt('属性名を入力');
1555
  if (attrName) {