Support escapes in markdown destination settings (#200911)

Support escaping `$` to prevent use as variable and escaping `/` inside of transforms
This commit is contained in:
Matt Bierner
2023-12-14 17:02:27 -08:00
committed by GitHub
parent 58bbee628c
commit 9b8f216b8c
2 changed files with 36 additions and 5 deletions

View File

@@ -153,7 +153,7 @@ function resolveCopyDestinationSetting(documentUri: vscode.Uri, fileName: string
['documentRelativeDirName', workspaceFolder ? path.posix.relative(workspaceFolder.path, documentDirName.path) : documentDirName.path], // Absolute parent directory path
['documentFileName', documentBaseName], // Full filename: file.md
['documentBaseName', documentBaseName.slice(0, documentBaseName.length - documentExtName.length)], // Just the name: file
['documentExtName', documentExtName.replace('.', '')], // Just the file ext: md
['documentExtName', documentExtName.replace('.', '')], // The document ext (without dot): md
['documentFilePath', documentUri.path], // Full document path
['documentRelativeFilePath', workspaceFolder ? path.posix.relative(workspaceFolder.path, documentUri.path) : documentUri.path], // Full document path relative to workspace
@@ -162,18 +162,28 @@ function resolveCopyDestinationSetting(documentUri: vscode.Uri, fileName: string
// File
['fileName', fileName], // Full file name
['fileExtName', path.extname(fileName).replace('.', '')], // File extension (without dot): png
]);
return outDest.replaceAll(/\$\{(\w+)(?:\/([^\}]+?)\/([^\}]+?)\/)?\}/g, (match, name, pattern, replacement) => {
return outDest.replaceAll(/(?<escape>\\\$)|(?<!\\)\$\{(?<name>\w+)(?:\/(?<pattern>(?:\\\/|[^\}])+?)\/(?<replacement>(?:\\\/|[^\}])+?)\/)?\}/g, (match, _escape, name, pattern, replacement, _offset, _str, groups) => {
if (groups?.['escape']) {
return '$';
}
const entry = vars.get(name);
if (!entry) {
if (typeof entry !== 'string') {
return match;
}
if (pattern && replacement) {
return entry.replace(new RegExp(pattern), replacement);
return entry.replace(new RegExp(replaceTransformEscapes(pattern)), replaceTransformEscapes(replacement));
}
return entry;
});
}
function replaceTransformEscapes(str: string): string {
return str.replaceAll(/\\\//g, '/');
}

View File

@@ -68,10 +68,31 @@ suite('resolveCopyDestination', () => {
assert.strictEqual(dest.toString(), 'test://projects/project/sub/img.gif');
});
test('transforms should support capture groups', async () => {
test('Transforms should support capture groups', async () => {
const documentUri = vscode.Uri.parse('test://projects/project/sub/readme.md');
const dest = resolveCopyDestination(documentUri, 'img.png', '${fileName/(.+)\\.(.+)/$2.$1/}', () => undefined);
assert.strictEqual(dest.toString(), 'test://projects/project/sub/png.img');
});
test('Should support escaping snippet variables ', async () => {
const documentUri = vscode.Uri.parse('test://projects/project/sub/readme.md');
// Escape leading '$'
assert.strictEqual(
resolveCopyDestination(documentUri, 'img.png', '\\${fileName}', () => undefined).toString(true),
'test://projects/project/sub/${fileName}');
// Escape closing '}'
assert.strictEqual(
resolveCopyDestination(documentUri, 'img.png', '${fileName\\}', () => undefined).toString(true),
'test://projects/project/sub/${fileName\\}');
});
test('Transforms should support escaped slashes', async () => {
const documentUri = vscode.Uri.parse('test://projects/project/sub/readme.md');
const dest = resolveCopyDestination(documentUri, 'img.png', '${fileName/(.+)/x\\/y/}.${fileExtName}', () => undefined);
assert.strictEqual(dest.toString(), 'test://projects/project/sub/x/y.png');
});
});