packages/react-devtools/app.html (241 lines of code) (raw):

<!DOCTYPE html> <html> <head> <title>React Developer Tools</title> <meta charset="utf8" /> <style> html { height: 100%; font-family: sans-serif; } body { height: 100%; margin: 0; padding: 0; background-color: #fff; color: #777d88; } .container { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; overflow: auto; } p { padding: 0; margin: 0; } .input { display: block; font-weight: 100; padding: 0 0.25rem; border: 1px solid #aaa; background-color: #fff; color: #666; } .link { color: #1478fa; text-decoration: none; } .link:hover { text-decoration: underline; } .waiting-header { padding: 0.5rem; display: inline-block; position: absolute; right: 0.5rem; top: 0.5rem; border-radius: 0.25rem; background-color: rgba(0,1,2,.6); color: white; border: none; font-weight: 100; font-style: italic; } .boxes { display: flex; flex-direction: column; align-items: stretch; justify-content: center; padding: 1rem; } .box { text-align: center; border-radius: 0.5rem; background-color: #f7f7f7; border: 1px solid #eee; color: #777d88; padding: 1rem; margin-top: 1rem; } .box:first-of-type { margin-top: 0; } .box-header { text-align: center; color: #5f6673; font-size: 1.25rem; margin-bottom: 0.5rem; } .box-content { line-height: 1.5rem; } #loading-status { text-align: center; margin-top: 1rem; } .prompt, .confirmation { margin-bottom: 0.25rem; } .confirmation { font-style: italic; } .hidden { display: none; } </style> </head> <body> <div id="container" class="container" style="-webkit-user-select: none; -webkit-app-region: drag;"> <div class="waiting-header">Waiting for React to connect…</div> <div class="boxes" style="-webkit-app-region: none;"> <div class="box"> <div class="box-header">React Native</div> <div class="box-content"> Open the <a id="rn-help-link" class="link" target="_blank" rel="noopener noreferrer" href="https://reactnative.dev/docs/debugging#accessing-the-in-app-developer-menu" >in-app developer menu</a> to connect. </div> </div> <div class="box"> <div class="box-header">React DOM</div> <div class="box-content"> <div id="box-content-prompt" class="prompt"> Add one of the following (click to copy): </div> <div id="box-content-confirmation" class="confirmation hidden"> Copied to clipboard. </div> <span class="input" contenteditable="true" id="localhost"></span> <span class="input" contenteditable="true" id="byip"></span> to the top of the page you want to debug, <br /> <strong>before</strong> importing React DOM. </div> </div> <div class="box"> <div class="box-header">Profiler</div> <div class="box-content"> Open the <a id="profiler" class="link" href="#" >Profiler tab</a> to inspect saved profiles. </div> </div> <div id="loading-status">Starting the server…</div> </div> </div> <script> const fs = require('fs'); let options; let useHttps = false; try { if (process.env.KEY && process.env.CERT) { options = { key: fs.readFileSync(process.env.KEY), cert: fs.readFileSync(process.env.CERT) }; useHttps = true; } } catch (err) { console.error('Failed to process SSL options - ', err); options = undefined; } const {clipboard} = require("electron"); const host = process.env.HOST || 'localhost'; const protocol = useHttps ? 'https' : 'http'; const port = Number(process.env.PORT || 8097); const localIp = require("ip").address(); const defaultPort = (port === 443 && useHttps) || (port === 80 && !useHttps); const server = defaultPort ? `${protocol}://${host}` : `${protocol}://${host}:${port}`; const serverIp = defaultPort ? `${protocol}://${localIp}` : `${protocol}://${localIp}:${port}`; const $ = document.querySelector.bind(document); let timeoutID; function selectAllAndCopy(event) { const element = event.target; if (window.getSelection) { const selection = window.getSelection(); const range = document.createRange(); range.selectNodeContents(element); selection.removeAllRanges(); selection.addRange(range); clipboard.writeText(event.target.textContent); const $promptDiv = $("#box-content-prompt"); const $confirmationDiv = $("#box-content-confirmation"); $promptDiv.classList.add('hidden'); $confirmationDiv.classList.remove('hidden'); if (timeoutID) { clearTimeout(timeoutID); } timeoutID = setTimeout(() => { $promptDiv.classList.remove('hidden'); $confirmationDiv.classList.add('hidden'); }, 1000); } } function openProfiler() { window.devtools .setContentDOMNode(document.getElementById("container")) .openProfiler(); } function attachListeners() { const link = $('#rn-help-link'); link.addEventListener('click', event => { event.preventDefault(); require('electron').shell.openExternal(link.href); }); const $localhost = $("#localhost"); $localhost.innerText = `<script src="${server}"></` + 'script>'; $localhost.addEventListener('click', selectAllAndCopy); $localhost.addEventListener('focus', selectAllAndCopy); const $byIp = $("#byip"); $byIp.innerText = `<script src="${serverIp}"></` + 'script>'; $byIp.addEventListener('click', selectAllAndCopy); $byIp.addEventListener('focus', selectAllAndCopy); const $profiler = $("#profiler"); $profiler.addEventListener('click', openProfiler); }; // Initially attach the listeners attachListeners(); let devtools; try { devtools = require("react-devtools-core/standalone").default; } catch (err) { alert( err.toString() + "\n\nDid you run `yarn` and `yarn run build` in packages/react-devtools-core?" ); } window.devtools = devtools; window.server = devtools .setContentDOMNode(document.getElementById("container")) .setDisconnectedCallback(attachListeners) .setStatusListener(function(status) { const element = document.getElementById("loading-status"); if (element) { element.innerText = status; } }) .startServer(port, host, options); </script> </body> </html>