Skip to content

Commit

Permalink
✨ Multiple extension specification
Browse files Browse the repository at this point in the history
  • Loading branch information
3ru committed Oct 3, 2023
1 parent ae7972d commit 131c79d
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 67 deletions.
88 changes: 56 additions & 32 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand All @@ -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;

Expand Down Expand Up @@ -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) => {
Expand Down
98 changes: 66 additions & 32 deletions src/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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('.')
}

/**
Expand All @@ -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),
)
}
15 changes: 12 additions & 3 deletions src/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down

0 comments on commit 131c79d

Please sign in to comment.