scaffolder: add support for copyWithoutRender to fetch:template

Signed-off-by: Mike Lewis <mtlewis@users.noreply.github.com>
This commit is contained in:
Mike Lewis
2021-07-02 18:17:43 +01:00
committed by Himanshu Mishra
parent cc43a3135e
commit cc8cf9e89c
@@ -34,6 +34,7 @@ export function createFetchTemplateAction(options: {
url: string;
targetPath?: string;
values: any;
copyWithoutRender?: string[];
}>({
id: 'fetch:template',
description:
@@ -60,8 +61,15 @@ export function createFetchTemplateAction(options: {
description: 'Values to pass on to the templating engine',
type: 'object',
},
// TODO(mtlewis/orkohunter): add copyWithoutRender support
//
copyWithoutRender: {
title: 'Copy Without Render',
description:
'Avoid rendering directories and files in the template',
type: 'array',
items: {
type: 'string',
},
},
// TODO(mtlewis/orkohunter): do we need to replicate the template extensions support
// from fetch:cookiecutter?
},
@@ -69,18 +77,28 @@ export function createFetchTemplateAction(options: {
},
async handler(ctx) {
ctx.logger.info('Fetching template content from remote URL');
const workDir = await ctx.createTemporaryDirectory();
const templateDir = resolvePath(workDir, 'template');
// Finally move the template result into the task workspace
const targetPath = ctx.input.targetPath ?? './';
const outputPath = path.resolve(ctx.workspacePath, targetPath);
if (!outputPath.startsWith(ctx.workspacePath)) {
throw new InputError(
`Fetch action targetPath may not specify a path outside the working directory`,
);
}
if (
ctx.input.copyWithoutRender &&
!Array.isArray(ctx.input.copyWithoutRender)
) {
throw new InputError(
'Fetch action input copyWithoutRender must be an Array',
);
}
await fetchContents({
reader,
integrations,
@@ -103,6 +121,15 @@ export function createFetchTemplateAction(options: {
cwd: templateDir,
dot: true,
});
const nonTemplatedFiles = new Set(
(
await Promise.all(
(ctx.input.copyWithoutRender || []).map(pattern =>
globby(pattern, { cwd: templateDir, dot: true }),
),
)
).flat(),
);
// Nice for Cookiecutter compat
//
@@ -116,7 +143,9 @@ export function createFetchTemplateAction(options: {
variableStart: '${{',
variableEnd: '}}',
},
// We don't want this builtin auto-escaping since it is escaping as HTML which will often be incorrect e.g. adds things like &quot;
// We don't want this builtin auto-escaping, since uses HTML escape sequences
// like `&quot;` - the correct way to escape strings in our case depends on
// the file type.
autoescape: false,
});
@@ -127,16 +156,24 @@ export function createFetchTemplateAction(options: {
templater.addFilter('jsonify', s => JSON.stringify(s));
for (const location of allFilesInTemplates) {
// handle variables in filenames
const filepath = templater.renderString(location, ctx.input.values);
const isTemplated = !nonTemplatedFiles.has(location);
const outputFilePath = resolvePath(
outputPath,
isTemplated
? templater.renderString(location, ctx.input.values)
: location,
);
const inputFileContents = await fs.readFile(
resolvePath(templateDir, location),
'utf-8',
);
// write file
await fs.outputFile(
resolvePath(outputPath, filepath),
templater.renderString(
await fs.readFile(resolvePath(templateDir, location), 'utf-8'),
ctx.input.values,
),
outputFilePath,
isTemplated
? templater.renderString(inputFileContents, ctx.input.values)
: inputFileContents,
);
}
},