in src/cache-view.ts [258:540]
getWebviewMarkup() {
const key = '%TABLE_ROWS%';
const searchButtonText = localize("search", "Search");
const saveButtonText = localize("save", "Save");
const keyColumnText = localize("key", "Key");
const valueColumnText = localize("value", "Value");
let html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${this.cmakeCacheEditorText}</title>
<style>
.select-default {
width: 300px;
height: 25px;
font-size: 13px;
font-family:sans-serif;
color: var(--vscode-settings-dropdownForeground);
background: var(--vscode-settings-dropdownBackground);
border: 1px solid var(--vscode-settings-dropdownBorder);
}
input {
height: 17px;
padding: 6px;
border: solid 1px;
font-size: 13px;
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
color: var(--vscode-settings-textInputForeground);
background: var(--vscode-settings-textInputBackground);
border: 1px solid var(--vscode-settings-textInputBorder);
}
.invalid-selection {
background-color: #4e2621;
}
.vscode-light .input-disabled {
background-color:rgba(255, 255, 255, 0.4);
color: rgb(138, 138, 138);
border: solid 1px rgb(201, 198, 198);
}
.vscode-dark .input-disabled {
background-color: rgba(255, 255, 255, 0.1);
color: rgb(167, 167, 167);
}
.vscode-high-contrast .input-disabled {
background-color: transparent;
color: #fff;
border: solid 1px rgb(255, 255, 255);
}
.vscode-high-contrast code > div {
background-color: #000
}
.vscode-high-contrast h1 {
border-color: #000
}
.vscode-light {
color: #1e1e1e
}
.vscode-dark {
color: #ddd
}
.vscode-high-contrast {
color: #fff
}
.vscode-light table,
.vscode-high-contrast table {
border: 1px solid var(--vscode-settings-textInputBorder);
border-collapse: collapse;
}
.vscode-dark table {
border: 1px solid rgb(255,255,255,0.3);
border-collapse: collapse;
}
.container {
padding-right: 15px;
padding-left: 15px;
width: 760px;
margin: 30px auto;
}
tr {
height: 25px;
}
.vscode-light th {
background: rgba(0,0,0,.1);
}
.vscode-dark th {
background: rgba(255,255,255,.1);
}
input#search {
width: 98%;
padding: 11px 0px 11px 11px;
margin: 10px 0;
color: var(--vscode-settings-textInputForeground);
background: var(--vscode-settings-textInputBackground);
border: 1px solid var(--vscode-settings-textInputBorder);
}
.invisible {
display: none;
}
button#save {
float: right;
padding: 10px 25px;
margin-top: 15px;
background: var(--vscode-button-background);
color: var(--vscode-button-foreground);
text-transform: uppercase;
font-weight: bold;
border: solid 1px var(--vscode-contrastBorder);
transition: 100ms ease-in-out;
}
button#save:hover {
cursor: pointer;
background-color: var(--vscode-button-hoverBackground);
}
button#save:focus,
button#save input:focus,
button#save select:focus {
outline: 1px solid -webkit-focus-ring-color;
outline-offset: 2px;
border-color: var(--vscode-focusBorder);
border: var(--vscode-focusBorder);
contrastBorder: var(--vscode-focusBorder);
contrastActiveBorder: var(--vscode-focusBorder);
}
button#save:active {
outline: none;
}
checkbox:active,
checkbox {
color: var(--vscode-settings-checkboxForeground);
background: var(--vscode-settings-checkboxForeground);
border: var(--vscode-settings-checkboxBorder);
}
.vscode-light cmake-input-bool input:checked,
.vscode-dark cmake-input-bool {
color: var(--vscode-settings-checkboxForeground);
background: var(--vscode-settings-checkboxForeground);
border: var(--vscode-settings-checkboxBorder);
}
.cmake-input-bool input:checked,
.cmake-input-bool:active,
.cmake-input-bool {
color: var(--vscode-settings-checkboxForeground);
background: var(--vscode-settings-checkboxForeground);
border: var(--vscode-settings-checkboxBorder);
}
a:focus,
input:focus,
select:focus,
textarea:focus {
outline: 1px solid -webkit-focus-ring-color;
outline-offset: -1px;
border-color: var(--vscode-focusBorder);
contrastBorder: var(--vscode-focusBorder);
contrastActiveBorder: var(--vscode-focusBorder);
}
</style>
<script>
const vscode = acquireVsCodeApi();
function updateCheckboxState(checkbox) {
checkbox.labels.forEach(label => label.textContent = checkbox.checked ? 'ON' : 'OFF');
}
function toggleKey(checkbox) {
updateCheckboxState(checkbox);
vscode.postMessage({key: checkbox.id, type: "Bool", value: checkbox.checked});
document.getElementById('not-saved').classList.remove('invisible');
}
function validateInput(editbox) {
const list = editbox.list;
if (list) {
let found = false;
for (const opt of list.options) {
if (opt.value === editbox.value) {
found = true;
break;
}
}
editbox.classList.toggle('invalid-selection', !found);
}
}
function edit(editbox) {
validateInput(editbox);
vscode.postMessage({key: editbox.id, type: "String", value: editbox.value});
document.getElementById('not-saved').classList.remove('invisible');
}
function save() {
document.getElementById('not-saved').classList.add('invisible');
vscode.postMessage(false);
}
function search() {
const filter = document.getElementById('search').value.toLowerCase();
for (const tr of document.querySelectorAll('.content-tr')) {
if (!tr.innerHTML.toLowerCase().includes(filter)) {
tr.classList.add('invisible');
} else {
tr.classList.remove('invisible');
}
}
}
window.onload = function() {
document.querySelectorAll('.cmake-input-bool').forEach(checkbox => {
updateCheckboxState(checkbox);
checkbox.onclick = () => toggleKey(checkbox);
});
document.querySelectorAll('.cmake-input-text').forEach(editbox => {
validateInput(editbox)
editbox.oninput = () => edit(editbox);
});
}
</script>
</head>
<body>
<div class="container">
<button id="save" onclick="save()">${saveButtonText}</button>
<h1>${this.cmakeCacheEditorText}<span class="invisible" id="not-saved">*</span></h1>
<input class="search" type="text" id="search" oninput="search()" placeholder="${searchButtonText}" autofocus>
<table style="width:100%">
<tr style="height: 25px;">
<th style="width: 30px"></th>
<th style="width: 1px; white-space: nowrap;">${keyColumnText}</th>
<th>${valueColumnText}</th>
</tr>
${key}
</table>
</div>
</body>
</html>`;
// compile a list of table rows that contain the key and value pairs
const tableRows = this._options.map(option => {
// HTML attributes may not contain literal double quotes or ambiguous ampersands
const escapeAttribute = (text: string) => text.replace(/&/g, "&").replace(/"/g, """);
// Escape HTML special characters that may not occur literally in any text
const escapeHtml = (text: string) =>
escapeAttribute(text)
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/'/g, "'")
.replace(/ /g, " "); // we are usually dealing with single line entities - avoid unintential line breaks
const id = escapeAttribute(option.key);
let editControls = '';
if (option.type === "Bool") {
editControls = `<input class="cmake-input-bool" id="${id}" type="checkbox" ${util.isTruthy(option.value) ? 'checked' : ''}>
<label id="LABEL_${id}" for="${id}"/>`;
} else {
const hasChoices = option.choices.length > 0;
if (hasChoices) {
editControls = `<datalist id="CHOICES_${id}">
${option.choices.map(ch => `<option value="${escapeAttribute(ch)}">`).join()}
</datalist>`;
}
editControls += `<input class="cmake-input-text" id="${id}" value="${escapeAttribute(option.value)}" style="width: 90%;"
type="text" ${hasChoices ? `list="CHOICES_${id}"` : ''}>`;
}
return `<tr class="content-tr">
<td></td>
<td title="${escapeAttribute(option.helpString)}">${escapeHtml(option.key)}</td>
<td>${editControls}</td>
</tr>`;
});
html = html.replace(key, tableRows.join(""));
return html;
}