From b5da952a957052bd16b746b6d85235c52de44176 Mon Sep 17 00:00:00 2001 From: Jono Kolnik <1164060+JonathanKolnik@users.noreply.github.com> Date: Thu, 7 Mar 2024 13:30:49 -0500 Subject: [PATCH] escape special characters in onlyStoryFiles filenames --- node-src/tasks/upload.test.ts | 21 +++++++++++++++++++++ node-src/tasks/upload.ts | 7 ++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/node-src/tasks/upload.test.ts b/node-src/tasks/upload.test.ts index de2477fd5..17a955ecf 100644 --- a/node-src/tasks/upload.test.ts +++ b/node-src/tasks/upload.test.ts @@ -164,6 +164,27 @@ describe('traceChangedFiles', () => { expect(ctx.onlyStoryFiles).toStrictEqual(Object.keys(deps)); }); + it('escapes special characters on context', async () => { + const deps = { './example-(new).stories.js': ['./example-(new).stories.js'] }; + findChangedDependencies.mockResolvedValue([]); + findChangedPackageFiles.mockResolvedValue([]); + getDependentStoryFiles.mockResolvedValue(deps); + + const ctx = { + env, + log, + http, + options: {}, + sourceDir: '/static/', + fileInfo: { statsPath: '/static/preview-stats.json' }, + git: { changedFiles: ['./example.js'] }, + turboSnap: {}, + } as any; + await traceChangedFiles(ctx, {} as any); + + expect(ctx.onlyStoryFiles).toStrictEqual(["./example-\\(\\new\\)\\.stories.js"]); + }); + it('does not run package dependency analysis if there are no metadata changes', async () => { const deps = { 123: ['./example.stories.js'] }; getDependentStoryFiles.mockResolvedValue(deps); diff --git a/node-src/tasks/upload.ts b/node-src/tasks/upload.ts index f2ee52839..4bc4c5a7c 100644 --- a/node-src/tasks/upload.ts +++ b/node-src/tasks/upload.ts @@ -37,6 +37,9 @@ interface PathSpec { contentLength: number; } +const escapedSpecialChars = '`$^*+?()[]'; +const specialCharsRegex = new RegExp(`([${escapedSpecialChars.split('').join('\\')}])`); + // Get all paths in rootDir, starting at dirname. // We don't want the paths to include rootDir -- so if rootDir = storybook-static, // paths will be like iframe.html rather than storybook-static/iframe.html @@ -154,7 +157,9 @@ export const traceChangedFiles = async (ctx: Context, task: Task) => { changedDependencyNames || [] ); if (onlyStoryFiles) { - ctx.onlyStoryFiles = Object.keys(onlyStoryFiles); + // Escape special characters in the filename so it does not conflict with picomatch + ctx.onlyStoryFiles = Object.keys(onlyStoryFiles).map((key) => key.split(specialCharsRegex).join('\\')); + if (!ctx.options.interactive) { if (!ctx.options.traceChanged) { ctx.log.info(