soiz1 commited on
Commit
12286b2
·
verified ·
1 Parent(s): 0087982

Update dev-tools.js

Browse files
Files changed (1) hide show
  1. dev-tools.js +160 -76
dev-tools.js CHANGED
@@ -9,7 +9,7 @@
9
  width: 100%;
10
  height: 300px; /* 適切な高さに調整 */
11
  background-color: #fff;
12
- border-top: 1px solid #ccc;
13
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
14
  z-index: 9999;
15
  display: flex;
@@ -78,40 +78,44 @@
78
  }
79
 
80
  /* Console スタイル */
81
- #console-log {
82
  white-space: pre-wrap;
83
- margin: 0;
84
- line-height: 1.4;
85
- flex: 1;
 
86
  }
87
 
88
  .console-input {
89
  width: 100%;
90
- background: #252a33;
91
- border: 1px solid #4fc3f7;
92
- color: #e0e0e0;
93
- padding: 8px;
94
- margin-top: 10px;
 
95
  }
96
 
97
  /* Elements スタイル */
98
- .elements-container {
99
  display: flex;
100
- flex: 1;
101
- overflow: hidden;
102
  }
103
 
104
  .dom-tree {
105
  font-family: monospace;
106
- flex: 1;
107
- overflow: auto;
108
- border-right: 1px solid #4fc3f7;
109
- padding-right: 10px;
 
110
  }
111
 
112
  .dom-node {
113
  margin-left: 15px;
114
- position: relative;
 
115
  }
116
 
117
  .dom-node.selected {
@@ -119,104 +123,119 @@
119
  }
120
 
121
  .dom-tag {
122
- color: #4fc3f7;
 
123
  }
124
 
125
  .dom-attr {
126
- color: #ff7043;
 
 
 
 
 
 
 
 
 
127
  }
128
 
129
  .css-panel {
130
  flex: 1;
131
- overflow: auto;
132
- padding-left: 10px;
133
  }
134
 
135
  .css-rule {
136
  margin-bottom: 15px;
137
- border: 1px solid #4fc3f7;
138
- padding: 8px;
 
139
  }
140
 
141
  .css-selector {
142
- color: #4fc3f7;
143
- margin-bottom: 5px;
 
144
  }
145
 
146
  .css-property {
147
  display: flex;
148
- margin-bottom: 3px;
149
  }
150
 
151
  .css-property-name {
152
- color: #69f0ae;
153
- min-width: 120px;
154
  }
155
 
156
  .css-property-value {
157
- color: #e0e0e0;
158
- flex: 1;
159
  }
160
 
161
  .css-toggle {
162
  margin-left: 10px;
163
- color: #ff7043;
164
- cursor: pointer;
165
  }
166
 
167
  /* Context Menu */
168
- .context-menu {
169
  position: absolute;
170
- background: #252a33;
171
- border: 1px solid #4fc3f7;
172
- z-index: 10000;
173
- min-width: 200px;
174
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
175
- display: none;
176
  }
177
 
178
  .context-menu-item {
179
  padding: 8px 15px;
180
- cursor: pointer;
 
181
  }
182
 
183
  .context-menu-item:hover {
184
  background: #4fc3f7;
185
- color: #000;
186
  }
187
 
188
  /* Storage スタイル */
189
- .storage-table {
190
  width: 100%;
191
- border-collapse: collapse;
 
192
  }
193
 
194
  .storage-table th, .storage-table td {
195
- border: 1px solid #4fc3f7;
196
- padding: 5px;
197
- text-align: left;
198
  }
199
 
200
  .storage-table th {
201
- background: #252a33;
202
  }
203
 
204
  .storage-actions {
205
  display: flex;
206
- gap: 5px;
207
  }
208
 
209
  .storage-btn {
210
  background: #4fc3f7;
211
- border: none;
212
- padding: 2px 5px;
213
- cursor: pointer;
 
214
  }
215
 
216
  .editable {
217
  cursor: pointer;
218
- padding: 2px 5px;
219
- border: 1px dashed transparent;
220
  }
221
 
222
  .editable:hover {
@@ -224,25 +243,33 @@
224
  }
225
 
226
  .add-btn {
227
- background: #69f0ae;
228
- color: #000;
229
- border: none;
230
- padding: 5px 10px;
231
- margin-top: 10px;
232
- cursor: pointer;
 
233
  }
234
 
235
- /* 各パネルの基本スタイル */
236
- #console-panel {
237
- background-color: #fff;
238
  }
239
 
240
- #elements-panel {
241
- background-color: #fff;
242
  }
243
 
244
- #storage-panel {
245
- background-color: #fff;
 
 
 
 
 
 
 
 
246
  }
247
  `;
248
  document.head.appendChild(style);
@@ -252,7 +279,6 @@
252
  let selectedElement = null;
253
  let selectedDOMNode = null;
254
 
255
- // 開発者ツールのUI構築
256
  // 開発者ツールのUI構築
257
  function createDevTools() {
258
  const container = document.createElement('div');
@@ -443,11 +469,11 @@
443
  try {
444
  const result = eval(e.target.value);
445
  if (result !== undefined) {
446
- logMessage('> ' + e.target.value, '#4fc3f7');
447
- logMessage('← ' + result, '#69f0ae');
448
  }
449
  } catch (err) {
450
- logMessage(err.message, '#ff5252');
451
  }
452
  e.target.value = '';
453
  }
@@ -461,21 +487,61 @@
461
  const original = console[method];
462
  console[method] = (...args) => {
463
  original.apply(console, args);
464
- const color = method === 'error' ? '#ff5252' : method === 'warn' ? '#ffab40' : '#e0e0e0';
465
- logMessage(args.join(' '), color);
466
  };
467
  });
468
 
469
  function logMessage(message, color) {
470
  const line = document.createElement('div');
471
  line.style.color = color;
472
- line.textContent = message;
473
  log.appendChild(line);
474
  log.scrollTop = log.scrollHeight;
475
  }
476
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
477
  return panel;
478
  }
 
 
479
  function buildDOMTree(node, parentElement, depth = 0) {
480
  if (node.nodeType === Node.ELEMENT_NODE) {
481
  const element = document.createElement('div');
@@ -520,8 +586,16 @@
520
  // 属性
521
  Array.from(node.attributes).forEach(attr => {
522
  const attrSpan = document.createElement('span');
523
- attrSpan.className = 'dom-attr';
524
  attrSpan.textContent = ` ${attr.name}="${attr.value}"`;
 
 
 
 
 
 
 
 
525
  element.appendChild(attrSpan);
526
  });
527
 
@@ -546,11 +620,20 @@
546
  } else if (node.nodeType === Node.TEXT_NODE && node.textContent.trim()) {
547
  const text = document.createElement('div');
548
  text.style.marginLeft = `${depth * 15}px`;
549
- text.style.color = '#e0e0e0';
550
  text.textContent = `"${node.textContent.trim()}"`;
 
 
 
 
 
 
 
 
551
  parentElement.appendChild(text);
552
  }
553
  }
 
554
  // Elementsパネルの作成
555
  function createElementsPanel() {
556
  const panel = document.createElement('div');
@@ -724,6 +807,7 @@
724
  }
725
  }
726
  }
 
727
  // Storageパネルの作成
728
  function createStoragePanel() {
729
  const panel = document.createElement('div');
 
9
  width: 100%;
10
  height: 300px; /* 適切な高さに調整 */
11
  background-color: #fff;
12
+ border-top: 1px solid #ddd;
13
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
14
  z-index: 9999;
15
  display: flex;
 
78
  }
79
 
80
  /* Console スタイル */
81
+ #console-log {
82
  white-space: pre-wrap;
83
+ margin: 0;
84
+ line-height: 1.4;
85
+ flex: 1;
86
+ color: #333;
87
  }
88
 
89
  .console-input {
90
  width: 100%;
91
+ background: #f5f5f5;
92
+ border: 1px solid #ddd;
93
+ color: #333;
94
+ padding: 8px;
95
+ margin-top: 10px;
96
+ font-family: monospace;
97
  }
98
 
99
  /* Elements スタイル */
100
+ .elements-container {
101
  display: flex;
102
+ flex: 1;
103
+ overflow: hidden;
104
  }
105
 
106
  .dom-tree {
107
  font-family: monospace;
108
+ flex: 1;
109
+ overflow: auto;
110
+ border-right: 1px solid #ddd;
111
+ padding-right: 10px;
112
+ color: #333;
113
  }
114
 
115
  .dom-node {
116
  margin-left: 15px;
117
+ position: relative;
118
+ line-height: 1.4;
119
  }
120
 
121
  .dom-node.selected {
 
123
  }
124
 
125
  .dom-tag {
126
+ color: #0066cc;
127
+ font-weight: bold;
128
  }
129
 
130
  .dom-attr {
131
+ color: #d33682;
132
+ }
133
+
134
+ .dom-attr.editable:hover {
135
+ text-decoration: underline;
136
+ cursor: pointer;
137
+ }
138
+
139
+ .dom-text {
140
+ color: #333;
141
  }
142
 
143
  .css-panel {
144
  flex: 1;
145
+ overflow: auto;
146
+ padding-left: 10px;
147
  }
148
 
149
  .css-rule {
150
  margin-bottom: 15px;
151
+ border: 1px solid #ddd;
152
+ padding: 8px;
153
+ background-color: #f9f9f9;
154
  }
155
 
156
  .css-selector {
157
+ color: #0066cc;
158
+ margin-bottom: 5px;
159
+ font-weight: bold;
160
  }
161
 
162
  .css-property {
163
  display: flex;
164
+ margin-bottom: 3px;
165
  }
166
 
167
  .css-property-name {
168
+ color: #d33682;
169
+ min-width: 120px;
170
  }
171
 
172
  .css-property-value {
173
+ color: #333;
174
+ flex: 1;
175
  }
176
 
177
  .css-toggle {
178
  margin-left: 10px;
179
+ color: #dc322f;
180
+ cursor: pointer;
181
  }
182
 
183
  /* Context Menu */
184
+ .context-menu {
185
  position: absolute;
186
+ background: #fff;
187
+ border: 1px solid #ddd;
188
+ z-index: 10000;
189
+ min-width: 200px;
190
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
191
+ display: none;
192
  }
193
 
194
  .context-menu-item {
195
  padding: 8px 15px;
196
+ cursor: pointer;
197
+ color: #333;
198
  }
199
 
200
  .context-menu-item:hover {
201
  background: #4fc3f7;
202
+ color: #000;
203
  }
204
 
205
  /* Storage スタイル */
206
+ .storage-table {
207
  width: 100%;
208
+ border-collapse: collapse;
209
+ margin-bottom: 10px;
210
  }
211
 
212
  .storage-table th, .storage-table td {
213
+ border: 1px solid #ddd;
214
+ padding: 5px;
215
+ text-align: left;
216
  }
217
 
218
  .storage-table th {
219
+ background: #f5f5f5;
220
  }
221
 
222
  .storage-actions {
223
  display: flex;
224
+ gap: 5px;
225
  }
226
 
227
  .storage-btn {
228
  background: #4fc3f7;
229
+ border: none;
230
+ padding: 2px 5px;
231
+ cursor: pointer;
232
+ border-radius: 3px;
233
  }
234
 
235
  .editable {
236
  cursor: pointer;
237
+ padding: 2px 5px;
238
+ border: 1px dashed transparent;
239
  }
240
 
241
  .editable:hover {
 
243
  }
244
 
245
  .add-btn {
246
+ background: #4fc3f7;
247
+ color: #000;
248
+ border: none;
249
+ padding: 5px 10px;
250
+ margin-top: 10px;
251
+ cursor: pointer;
252
+ border-radius: 3px;
253
  }
254
 
255
+ .json-object {
256
+ color: #268bd2;
 
257
  }
258
 
259
+ .json-string {
260
+ color: #2aa198;
261
  }
262
 
263
+ .json-number {
264
+ color: #d33682;
265
+ }
266
+
267
+ .json-boolean {
268
+ color: #b58900;
269
+ }
270
+
271
+ .json-null {
272
+ color: #6c71c4;
273
  }
274
  `;
275
  document.head.appendChild(style);
 
279
  let selectedElement = null;
280
  let selectedDOMNode = null;
281
 
 
282
  // 開発者ツールのUI構築
283
  function createDevTools() {
284
  const container = document.createElement('div');
 
469
  try {
470
  const result = eval(e.target.value);
471
  if (result !== undefined) {
472
+ logMessage('> ' + e.target.value, '#0066cc');
473
+ logMessage('← ' + formatOutput(result), '#2aa198');
474
  }
475
  } catch (err) {
476
+ logMessage(err.message, '#dc322f');
477
  }
478
  e.target.value = '';
479
  }
 
487
  const original = console[method];
488
  console[method] = (...args) => {
489
  original.apply(console, args);
490
+ const color = method === 'error' ? '#dc322f' : method === 'warn' ? '#b58900' : '#586e75';
491
+ logMessage(args.map(arg => formatOutput(arg)).join(' '), color);
492
  };
493
  });
494
 
495
  function logMessage(message, color) {
496
  const line = document.createElement('div');
497
  line.style.color = color;
498
+ line.innerHTML = message;
499
  log.appendChild(line);
500
  log.scrollTop = log.scrollHeight;
501
  }
502
 
503
+ // 出力をフォーマットする関数
504
+ function formatOutput(output) {
505
+ if (output === null) {
506
+ return '<span class="json-null">null</span>';
507
+ }
508
+ if (output === undefined) {
509
+ return '<span class="json-null">undefined</span>';
510
+ }
511
+ if (typeof output === 'boolean') {
512
+ return `<span class="json-boolean">${output}</span>`;
513
+ }
514
+ if (typeof output === 'number') {
515
+ return `<span class="json-number">${output}</span>`;
516
+ }
517
+ if (typeof output === 'string') {
518
+ return `<span class="json-string">"${output}"</span>`;
519
+ }
520
+ if (typeof output === 'function') {
521
+ return `<span class="json-object">function ${output.name}() { ... }</span>`;
522
+ }
523
+ if (Array.isArray(output)) {
524
+ return `<span class="json-object">[${output.map(formatOutput).join(', ')}]</span>`;
525
+ }
526
+ if (typeof output === 'object') {
527
+ try {
528
+ return `<span class="json-object">${JSON.stringify(output, null, 2)
529
+ .replace(/"([^"]+)":/g, '<span class="json-string">"$1"</span>:')
530
+ .replace(/"([^"]+)"/g, '<span class="json-string">"$1"</span>')
531
+ .replace(/\b(true|false)\b/g, '<span class="json-boolean">$1</span>')
532
+ .replace(/\b(null)\b/g, '<span class="json-null">$1</span>')
533
+ .replace(/\b(\d+)\b/g, '<span class="json-number">$1</span>')}</span>`;
534
+ } catch (e) {
535
+ return `<span class="json-object">${output.toString()}</span>`;
536
+ }
537
+ }
538
+ return output;
539
+ }
540
+
541
  return panel;
542
  }
543
+
544
+ // DOMツリーを構築する関数
545
  function buildDOMTree(node, parentElement, depth = 0) {
546
  if (node.nodeType === Node.ELEMENT_NODE) {
547
  const element = document.createElement('div');
 
586
  // 属性
587
  Array.from(node.attributes).forEach(attr => {
588
  const attrSpan = document.createElement('span');
589
+ attrSpan.className = 'dom-attr editable';
590
  attrSpan.textContent = ` ${attr.name}="${attr.value}"`;
591
+ attrSpan.onclick = (e) => {
592
+ e.stopPropagation();
593
+ const newValue = prompt(`属性 ${attr.name} の値を編集`, attr.value);
594
+ if (newValue !== null) {
595
+ node.setAttribute(attr.name, newValue);
596
+ refreshElementsPanel();
597
+ }
598
+ };
599
  element.appendChild(attrSpan);
600
  });
601
 
 
620
  } else if (node.nodeType === Node.TEXT_NODE && node.textContent.trim()) {
621
  const text = document.createElement('div');
622
  text.style.marginLeft = `${depth * 15}px`;
623
+ text.className = 'dom-text';
624
  text.textContent = `"${node.textContent.trim()}"`;
625
+ text.onclick = (e) => {
626
+ e.stopPropagation();
627
+ const newText = prompt('テキストを編集', node.textContent.trim());
628
+ if (newText !== null) {
629
+ node.textContent = newText;
630
+ refreshElementsPanel();
631
+ }
632
+ };
633
  parentElement.appendChild(text);
634
  }
635
  }
636
+
637
  // Elementsパネルの作成
638
  function createElementsPanel() {
639
  const panel = document.createElement('div');
 
807
  }
808
  }
809
  }
810
+
811
  // Storageパネルの作成
812
  function createStoragePanel() {
813
  const panel = document.createElement('div');