Merge pull request #3530 from github/koesie10/config-template

Add helper for substituting config variables
This commit is contained in:
Koen Vlaswinkel 2024-04-05 11:15:33 +02:00 коммит произвёл GitHub
Родитель 8ccca1381a 8cb2b34992
Коммит 351bc648ef
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
2 изменённых файлов: 136 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,57 @@
// Based on https://github.com/microsoft/vscode/blob/edfd5b8ba54d50f3f5c2ebee877af088803def88/src/vs/base/common/labels.ts#L316C1-L400
/**
* Helper to insert values for specific template variables into the string. E.g. "this ${is} a ${template}" can be
* passed to this function together with an object that maps "is" and "template" to strings to have them replaced.
*
* @param template string to which template is applied
* @param values the values of the templates to use
*/
export function substituteConfigVariables(
template: string,
values: {
[key: string]: string | undefined | null;
},
): string {
const segments: string[] = [];
let inVariable = false;
let currentValue = "";
for (const char of template) {
// Beginning of variable
if (char === "$" || (inVariable && char === "{")) {
if (currentValue) {
segments.push(currentValue);
}
currentValue = "";
inVariable = true;
}
// End of variable
else if (char === "}" && inVariable) {
const resolved = values[currentValue];
// Variable
if (resolved && resolved.length > 0) {
segments.push(resolved);
}
// If the variable, doesn't exist, we discard it (i.e. replace it by the empty string)
currentValue = "";
inVariable = false;
}
// Text or Variable Name
else {
currentValue += char;
}
}
// Tail
if (currentValue && !inVariable) {
segments.push(currentValue);
}
return segments.join("");
}

Просмотреть файл

@ -0,0 +1,79 @@
import { substituteConfigVariables } from "../../../src/common/config-template";
describe("substituteConfigVariables", () => {
const values = {
userHome: "/home/your-username",
workspaceFolder: "/home/your-username/your-project",
workspaceFolderBasename: "your-project",
pathSeparator: "/",
owner: "github",
name: "vscode-codeql",
language: "java",
};
const testCases = [
{
template: ".github/codeql/extensions/${name}-${language}",
expected: ".github/codeql/extensions/vscode-codeql-java",
},
{
template: "${owner}/${name}-${language}",
expected: "github/vscode-codeql-java",
},
{
template: "models/${group}.model.yml",
expected: "models/.model.yml",
},
{
template:
"${workspaceFolder}${pathSeparator}.github/workflows/codeql-analysis.yml",
expected:
"/home/your-username/your-project/.github/workflows/codeql-analysis.yml",
},
{
template:
"${workspaceFolder/.github/codeql/extensions/${name}-${language}",
expected: "workspaceFolder/.github/codeql/extensions/vscode-codeql-java",
},
{
template: "}${workspaceFolder}/.github/workflows/codeql-analysis.yml",
expected:
"}/home/your-username/your-project/.github/workflows/codeql-analysis.yml",
},
{
template: "Foo Bar",
expected: "Foo Bar",
},
{
template: "Foo${}Bar",
expected: "FooBar",
},
{
template: "$FooBar",
expected: "",
},
{
template: "}FooBar",
expected: "}FooBar",
},
{
template: "Foo ${name} Bar",
expected: "Foo vscode-codeql Bar",
},
{
template: "Foo ${name} Bar ${owner}",
expected: "Foo vscode-codeql Bar github",
},
{
template: "Foo ${nmae} Bar ${owner}",
expected: "Foo Bar github",
},
];
test.each(testCases)(
"result of $template is $expected",
({ template, expected }) => {
expect(substituteConfigVariables(template, values)).toEqual(expected);
},
);
});