// dev-tools.js document.addEventListener('DOMContentLoaded', () => { // スタイル定義 const style = document.createElement('style'); style.textContent = ` :root { --devtools-blue: #1a1c2c; --neon-blue: #00f3ff; --dark-layer: rgba(0, 0, 0, 0.9); } .devtools-btn { position: fixed; bottom: 20px; right: 20px; background: var(--devtools-blue); color: var(--neon-blue); border: 2px solid var(--neon-blue); padding: 10px 20px; cursor: pointer; border-radius: 5px; font-family: 'Courier New', monospace; z-index: 10000; transition: all 0.3s; } .devtools-btn:hover { box-shadow: 0 0 15px var(--neon-blue); } .devtools-panel { position: fixed; bottom: 0; right: 0; width: 100%; height: 60vh; background: var(--dark-layer); border-top: 3px solid var(--neon-blue); color: white; font-family: 'Courier New', monospace; display: none; z-index: 9999; } .tabs { display: flex; background: var(--devtools-blue); border-bottom: 1px solid var(--neon-blue); } .tab { padding: 10px 20px; cursor: pointer; border-right: 1px solid var(--neon-blue); } .tab.active { background: var(--neon-blue); color: var(--devtools-blue); } .panel-content { padding: 15px; overflow-y: auto; height: calc(100% - 50px); } .dom-node { margin-left: 15px; cursor: pointer; } .dom-node::before { content: '▶'; margin-right: 5px; transition: transform 0.2s; } .dom-node.expanded::before { transform: rotate(90deg); } .console-input { width: 100%; background: transparent; border: 1px solid var(--neon-blue); color: white; padding: 5px; margin-top: 10px; } .console-log { white-space: pre-wrap; color: var(--neon-blue); } `; document.head.appendChild(style); // 開発者ツール起動ボタン const openBtn = document.createElement('button'); openBtn.className = 'devtools-btn'; openBtn.textContent = '🛠 Open DevTools'; document.body.appendChild(openBtn); // 開発者ツールパネル const panel = document.createElement('div'); panel.className = 'devtools-panel'; // タブインターフェイス const tabs = ['Console', 'Elements', 'Styles'].map(name => { const tab = document.createElement('div'); tab.className = 'tab'; tab.textContent = name; return tab; }); const tabContent = document.createElement('div'); tabContent.className = 'panel-content'; // コンソールタブ const consoleInput = document.createElement('input'); consoleInput.className = 'console-input'; consoleInput.placeholder = 'Enter JavaScript...'; const consoleLog = document.createElement('pre'); consoleLog.className = 'console-log'; // ログキャプチャ const originalConsoleLog = console.log; console.log = (...args) => { originalConsoleLog(...args); consoleLog.textContent += args.join(' ') + '\n'; }; // DOMインスペクタ function createDOMTree(node, depth = 0) { const element = document.createElement('div'); element.className = 'dom-node'; element.textContent = node.nodeName.toLowerCase(); if (node.childNodes.length > 0) { node.childNodes.forEach(child => { if (child.nodeType === Node.ELEMENT_NODE) { element.appendChild(createDOMTree(child, depth + 1)); } }); } element.addEventListener('click', (e) => { e.stopPropagation(); element.classList.toggle('expanded'); }); return element; } // タブ切り替え tabs.forEach((tab, index) => { tab.addEventListener('click', () => { tabs.forEach(t => t.classList.remove('active')); tab.classList.add('active'); tabContent.innerHTML = ''; switch(index) { case 0: tabContent.appendChild(consoleLog); tabContent.appendChild(consoleInput); break; case 1: tabContent.appendChild(createDOMTree(document.documentElement)); break; } }); }); // パネル構成 panel.appendChild(tabs.reduce((container, tab) => { container.appendChild(tab); return container; }, document.createElement('div'))); panel.appendChild(tabContent); // イベントハンドラ openBtn.addEventListener('click', () => { panel.style.display = 'block'; tabs[0].click(); }); consoleInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { try { eval(e.target.value); } catch (err) { console.log('Error:', err); } e.target.value = ''; } }); document.body.appendChild(panel); });