From abcc2b08c1e36d348be73ceb4c13b649650ec13a Mon Sep 17 00:00:00 2001 From: Martin Seemann Date: Sun, 2 May 2021 19:01:42 +0200 Subject: [PATCH 1/2] Make cache editing more robust against corner cases --- src/api.ts | 2 + src/cache-view.ts | 99 ++++++++++++++++++++++++++++++++++------------- src/cache.ts | 88 +++++++++++++++++++++++++++++++---------- 3 files changed, 142 insertions(+), 47 deletions(-) diff --git a/src/api.ts b/src/api.ts index e55c05836..52bad91ac 100644 --- a/src/api.ts +++ b/src/api.ts @@ -90,6 +90,8 @@ export interface CacheEntryProperties { value: any; /** Whether this entry is ADVANCED, meaning it hidden from the user. */ advanced: boolean; + /** List of allowed values, as specified by STRINGS property */ + choices: string[]; } /** diff --git a/src/cache-view.ts b/src/cache-view.ts index d488bb2fd..837bf31fd 100644 --- a/src/cache-view.ts +++ b/src/cache-view.ts @@ -15,6 +15,8 @@ const localize: nls.LocalizeFunc = nls.loadMessageBundle(); export interface IOption { key: string; // same as CMake cache variable key names type: string; // "Bool" for boolean and "String" for anything else for now + helpString: string; + choices: string[]; value: string; // value from the cache file or changed in the UI dirty: boolean; // if the variable was edited in the UI } @@ -224,7 +226,7 @@ export class ConfigurationWebview { // Static cache entries are set automatically by CMake, overriding any value set by the user in this view. // Not useful to show these entries in the list. if (entry.type !== api.CacheEntryType.Static) { - options.push({ key: entry.key, type: (entry.type === api.CacheEntryType.Bool) ? "Bool" : "String", value: entry.value, dirty: false }); + options.push({ key: entry.key, helpString: entry.helpString, choices: entry.choices, type: (entry.type === api.CacheEntryType.Bool) ? "Bool" : "String", value: entry.value, dirty: false }); } } @@ -288,6 +290,10 @@ export class ConfigurationWebview { 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); @@ -420,16 +426,30 @@ export class ConfigurationWebview { @@ -467,26 +498,42 @@ export class ConfigurationWebview { // 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) => { + return text.replace(/&/g, "&").replace(/"/g, """); + }; + // Escape HTML special characters that may not occur literally in any text + const escapeHtml = (text: string) => { + return escapeAttribute(text) + .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") { - return ` - - ${option.key} - - - - - `; + editControls = ` +