diff --git a/dist/index.js b/dist/index.js index 4c6c54f..aea900f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -18460,21 +18460,35 @@ exports.isFileExists = isFileExists; /** * Replace the part with '**' with the rest */ -function replaceWildcard(inputArray, outputArray) { - const output = [...outputArray]; +const replaceWildcardPath = (inputArray, outputArray) => { const indexOfAsteriskAsterisk = outputArray.indexOf('**'); - if (indexOfAsteriskAsterisk !== -1) { - output.splice(indexOfAsteriskAsterisk, 1, ...inputArray.slice(indexOfAsteriskAsterisk)); - } - return output; -} + // Return copy with no references + if (indexOfAsteriskAsterisk === -1) + return [...outputArray]; + return [ + ...outputArray.slice(0, indexOfAsteriskAsterisk), + ...inputArray.slice(indexOfAsteriskAsterisk), + ]; +}; /** - * Extracts the extension from a filename string + * Replaces the wildcard '*' in the output filename with the corresponding segments from the input filename, + * while preserving any modifiers after the wildcard in the output filename. */ -function extractFileExtension(filename) { - const match = filename.match(/\.\w+(\.\w+)?$/); - return match ? match[0] : null; -} +const replaceWildcardFilename = (inputFilenameWithoutExt, outputFilenameWithoutExt) => { + if (!inputFilenameWithoutExt.includes('.')) { + return outputFilenameWithoutExt.replace('*', inputFilenameWithoutExt); + } + // Split filenames into segments based on '.' + const inputSegmentsReversed = inputFilenameWithoutExt.split('.').reverse(); + const outputSegmentsReversed = outputFilenameWithoutExt.split('.').reverse(); + const wildcardIndex = outputSegmentsReversed.indexOf('*'); + // Construct the new filename by replacing the wildcard with the corresponding segments from the input filename + const mergedSegments = [ + ...outputSegmentsReversed.slice(0, wildcardIndex), + ...inputSegmentsReversed.slice(wildcardIndex), + ]; + return mergedSegments.reverse().join('.'); +}; /** * Generates an array of output file paths based on the provided array of input file paths * @@ -18485,28 +18499,31 @@ function extractFileExtension(filename) { * */ const generateOutputFilePaths = (inputFilePaths, outputFilePath) => { - const outputSegments = outputFilePath.replace('./', '').split('/'); - const outputFilePattern = outputSegments.pop(); - const outputFileExt = extractFileExtension(outputFilePattern) || ''; - const outputFilenameWithoutExt = outputFilePattern.replace(outputFileExt, ''); - return inputFilePaths.map((inputFilePath) => { - const inputSegments = inputFilePath.split('/'); + const outputSegments = path_1.default.normalize(outputFilePath).split(path_1.default.sep); + const outputFileName = outputSegments.pop(); + const outputFilenameWithoutExt = path_1.default.basename(outputFileName, path_1.default.extname(outputFileName)); + /** + * Generates a single output path based on the provided input file path and output file extension. + */ + const generateOutputPath = (inputFilePath) => { + const inputSegments = path_1.default.normalize(inputFilePath).split(path_1.default.sep); const inputFile = inputSegments.pop(); - const inputFileExt = extractFileExtension(inputFile) || ''; - const inputFilenameWithoutExt = inputFile.replace(inputFileExt, ''); - const resolvedPathSegments = replaceWildcard(inputSegments, outputSegments); // Resolve path segments - // If output file pattern contains '*', replace it with the input filename + const inputFileExt = path_1.default.extname(inputFile); + const inputFilenameWithoutExt = path_1.default.basename(inputFile, inputFileExt); + const resolvedPathSegments = replaceWildcardPath(inputSegments, outputSegments); if (outputFilenameWithoutExt.includes('*')) { - const finalExt = outputFileExt || inputFileExt; // If output extension isn't specified, use input file extension - const finalFilename = `${inputFilenameWithoutExt}${finalExt}`; // Concatenate filename and extension - resolvedPathSegments.push(finalFilename); + // If the output file pattern contains a wildcard '*', replace it with the input file name + const finalFilename = replaceWildcardFilename(inputFilenameWithoutExt, outputFilenameWithoutExt); + // Use the extension of the input file and not the extension specified for the output file. + resolvedPathSegments.push(`${finalFilename}${inputFileExt}`); } else { - // Otherwise, use the specified output filename - resolvedPathSegments.push(outputFilePattern); + // Otherwise, use the specified output file name + resolvedPathSegments.push(outputFileName); } - return resolvedPathSegments.join('/'); - }); + return path_1.default.join(...resolvedPathSegments); + }; + return inputFilePaths.flatMap((inputFilePath) => generateOutputPath(inputFilePath)); }; exports.generateOutputFilePaths = generateOutputFilePaths; @@ -18868,9 +18885,16 @@ const path_1 = __importDefault(__nccwpck_require__(1017)); const utils_1 = __nccwpck_require__(6218); const error_1 = __nccwpck_require__(2747); const isValidFileExt = (filename) => { - // Allow input file extension inheritance by asterisk in addition to normal file formats - const fileExts = [...const_1.availableFileExtensions, '*']; - return fileExts.some((type) => filename.endsWith(type)); + const availabilities = new Set([...const_1.availableFileExtensions, '*']); + const fileExt = path_1.default.extname(filename); + if (fileExt.includes('{')) { + const fileExts = fileExt + .replace(/[{}.]/g, '') + .split(',') + .map((ext) => `.${ext}`); + return fileExts.every((ext) => availabilities.has(ext)); + } + return availabilities.has(fileExt); }; exports.isValidFileExt = isValidFileExt; const commandValidator = async (userCommand, match) => { diff --git a/src/file.ts b/src/file.ts index 45873ed..96562c0 100644 --- a/src/file.ts +++ b/src/file.ts @@ -35,27 +35,44 @@ export const isFileExists = async (inputPath: string) => { /** * Replace the part with '**' with the rest */ -function replaceWildcard(inputArray: string[], outputArray: string[]) { - const output = [...outputArray] +const replaceWildcardPath = ( + inputArray: string[], + outputArray: string[], +): string[] => { const indexOfAsteriskAsterisk = outputArray.indexOf('**') + // Return copy with no references + if (indexOfAsteriskAsterisk === -1) return [...outputArray] - if (indexOfAsteriskAsterisk !== -1) { - output.splice( - indexOfAsteriskAsterisk, - 1, - ...inputArray.slice(indexOfAsteriskAsterisk), - ) - } - - return output + return [ + ...outputArray.slice(0, indexOfAsteriskAsterisk), + ...inputArray.slice(indexOfAsteriskAsterisk), + ] } /** - * Extracts the extension from a filename string + * Replaces the wildcard '*' in the output filename with the corresponding segments from the input filename, + * while preserving any modifiers after the wildcard in the output filename. */ -function extractFileExtension(filename: string): string | null { - const match = filename.match(/\.\w+(\.\w+)?$/) - return match ? match[0] : null +const replaceWildcardFilename = ( + inputFilenameWithoutExt: string, + outputFilenameWithoutExt: string, +): string => { + if (!inputFilenameWithoutExt.includes('.')) { + return outputFilenameWithoutExt.replace('*', inputFilenameWithoutExt) + } + + // Split filenames into segments based on '.' + const inputSegmentsReversed = inputFilenameWithoutExt.split('.').reverse() + const outputSegmentsReversed = outputFilenameWithoutExt.split('.').reverse() + + const wildcardIndex = outputSegmentsReversed.indexOf('*') + + // Construct the new filename by replacing the wildcard with the corresponding segments from the input filename + const mergedSegments = [ + ...outputSegmentsReversed.slice(0, wildcardIndex), + ...inputSegmentsReversed.slice(wildcardIndex), + ] + return mergedSegments.reverse().join('.') } /** @@ -71,29 +88,46 @@ export const generateOutputFilePaths = ( inputFilePaths: string[], outputFilePath: string, ): string[] => { - const outputSegments = outputFilePath.replace('./', '').split('/') - const outputFilePattern = outputSegments.pop()! - const outputFileExt = extractFileExtension(outputFilePattern) || '' - const outputFilenameWithoutExt = outputFilePattern.replace(outputFileExt, '') + const outputSegments = path.normalize(outputFilePath).split(path.sep) + const outputFileName = outputSegments.pop()! + + const outputFilenameWithoutExt = path.basename( + outputFileName, + path.extname(outputFileName), + ) - return inputFilePaths.map((inputFilePath) => { - const inputSegments = inputFilePath.split('/') + /** + * Generates a single output path based on the provided input file path and output file extension. + */ + const generateOutputPath = (inputFilePath: string): string => { + const inputSegments = path.normalize(inputFilePath).split(path.sep) const inputFile = inputSegments.pop()! - const inputFileExt = extractFileExtension(inputFile) || '' - const inputFilenameWithoutExt = inputFile.replace(inputFileExt, '') + const inputFileExt = path.extname(inputFile) + const inputFilenameWithoutExt = path.basename(inputFile, inputFileExt) - const resolvedPathSegments = replaceWildcard(inputSegments, outputSegments) // Resolve path segments + const resolvedPathSegments = replaceWildcardPath( + inputSegments, + outputSegments, + ) - // If output file pattern contains '*', replace it with the input filename if (outputFilenameWithoutExt.includes('*')) { - const finalExt = outputFileExt || inputFileExt // If output extension isn't specified, use input file extension - const finalFilename = `${inputFilenameWithoutExt}${finalExt}` // Concatenate filename and extension - resolvedPathSegments.push(finalFilename) + // If the output file pattern contains a wildcard '*', replace it with the input file name + const finalFilename = replaceWildcardFilename( + inputFilenameWithoutExt, + outputFilenameWithoutExt, + ) + + // Use the extension of the input file and not the extension specified for the output file. + resolvedPathSegments.push(`${finalFilename}${inputFileExt}`) } else { - // Otherwise, use the specified output filename - resolvedPathSegments.push(outputFilePattern) + // Otherwise, use the specified output file name + resolvedPathSegments.push(outputFileName) } - return resolvedPathSegments.join('/') - }) + return path.join(...resolvedPathSegments) + } + + return inputFilePaths.flatMap((inputFilePath) => + generateOutputPath(inputFilePath), + ) } diff --git a/src/validate.ts b/src/validate.ts index 972ff17..c89db5e 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -4,9 +4,18 @@ import { postError, removeSymbols } from './utils' import { COMMAND_USAGE, INVALID_FILE_EXTENSION } from './error' export const isValidFileExt = (filename: string): boolean => { - // Allow input file extension inheritance by asterisk in addition to normal file formats - const fileExts = [...availableFileExtensions, '*'] - return fileExts.some((type) => filename.endsWith(type)) + const availabilities = new Set([...availableFileExtensions, '*']) + const fileExt = path.extname(filename) + + if (fileExt.includes('{')) { + const fileExts = fileExt + .replace(/[{}.]/g, '') + .split(',') + .map((ext) => `.${ext}`) + return fileExts.every((ext) => availabilities.has(ext)) + } + + return availabilities.has(fileExt) } export const commandValidator = async (