Inspector: Add a basic style sheet inspector

Choosing options from the `<select>` will load and display that style
sheet's source text, with some checks to make sure that the text that
just loaded is the one we currently want.

The UI is a little goofy when scrolling, as it uses `position: sticky`
which we don't implement yet. But that's just more motivation to
implement it! :^)
This commit is contained in:
Sam Atkins
2024-08-23 11:18:35 +01:00
committed by Sam Atkins
parent 49b2eb5f51
commit da171c3230
18 changed files with 270 additions and 2 deletions

View File

@@ -1,3 +1,7 @@
:root {
--code-font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
@media (prefers-color-scheme: dark) {
:root {
--background: rgb(23, 23, 23);
@@ -174,6 +178,17 @@ body {
overflow: auto scroll;
}
.tab-header {
position: sticky;
top: 2px; /* FIXME: Remove this when https://github.com/LadybirdBrowser/ladybird/issues/1245 is resolved. */
left: 0;
right: 0;
background-color: var(--tab-controls);
border-top: 2px solid var(--background);
display: flex;
padding: 0.5em;
}
details > :not(:first-child) {
display: list-item;
list-style: none inside;
@@ -204,7 +219,7 @@ details > :not(:first-child) {
}
.console {
font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-family: var(--code-font-family);
width: 100%;
height: 100%;
}
@@ -330,3 +345,14 @@ details > :not(:first-child) {
padding: 4px;
text-align: left;
}
#style-sheet-picker {
flex-grow: 1;
}
#style-sheet-source {
font-size: 10pt;
font-family: var(--code-font-family);
white-space: pre;
padding: 0.5em;
}

View File

@@ -199,6 +199,97 @@ inspector.addAttributeToDOMNodeID = nodeID => {
pendingEditDOMNode = null;
};
inspector.setStyleSheets = styleSheets => {
const styleSheetPicker = document.getElementById("style-sheet-picker");
const styleSheetSource = document.getElementById("style-sheet-source");
styleSheetPicker.replaceChildren();
styleSheetSource.innerHTML = "";
function addOption(styleSheet, text) {
const option = document.createElement("option");
option.innerText = text;
if (styleSheet.type) {
option.dataset["type"] = styleSheet.type;
}
if (styleSheet.domNodeId) {
option.dataset["domNodeId"] = styleSheet.domNodeId;
}
if (styleSheet.url) {
option.dataset["url"] = styleSheet.url;
}
styleSheetPicker.add(option);
}
if (styleSheets.length > 0) {
let styleElementIndex = 1;
for (const styleSheet of styleSheets) {
switch (styleSheet.type) {
case "StyleElement":
addOption(styleSheet, `Style element #${styleElementIndex++}`);
break;
case "LinkElement":
addOption(styleSheet, styleSheet.url);
break;
case "ImportRule":
addOption(styleSheet, styleSheet.url);
break;
case "UserAgent":
addOption(styleSheet, `User agent: ${styleSheet.url}`);
break;
case "UserStyle":
addOption(styleSheet, "User style");
break;
}
}
styleSheetPicker.disabled = false;
} else {
addOption({}, "No style sheets found");
styleSheetPicker.disabled = true;
}
styleSheetPicker.selectedIndex = 0;
if (!styleSheetPicker.disabled) {
loadStyleSheet();
}
};
const loadStyleSheet = () => {
const styleSheetPicker = document.getElementById("style-sheet-picker");
const styleSheetSource = document.getElementById("style-sheet-source");
const selectedOption = styleSheetPicker.selectedOptions[0];
styleSheetSource.innerHTML = "Loading...";
inspector.requestStyleSheetSource(
selectedOption.dataset["type"],
selectedOption.dataset["domNodeId"],
selectedOption.dataset["url"]
);
};
inspector.setStyleSheetSource = (identifier, sourceBase64) => {
const styleSheetPicker = document.getElementById("style-sheet-picker");
const styleSheetSource = document.getElementById("style-sheet-source");
const selectedOption = styleSheetPicker.selectedOptions[0];
// Make sure this is the source for the currently-selected style sheet.
// NOTE: These are != not !== intentionally.
if (
identifier.type != selectedOption.dataset["type"] ||
identifier.domNodeId != selectedOption.dataset["domNodeId"] ||
identifier.url != selectedOption.dataset["url"]
) {
console.log(
JSON.stringify(identifier),
"doesn't match",
JSON.stringify(selectedOption.dataset)
);
return;
}
styleSheetSource.innerHTML = decodeBase64(sourceBase64);
};
inspector.createPropertyTables = (computedStyle, resolvedStyle, customProperties) => {
const createPropertyTable = (tableID, properties) => {
let oldTable = document.getElementById(tableID);