Optional generation of Images extension. Make extensionOutputPath optional for Images and Colors cause it's not needed if no extensionName are provided

This commit is contained in:
2025-07-17 10:23:05 +02:00
parent 4426091dcb
commit e22f9ba894
12 changed files with 132 additions and 97 deletions

View File

@@ -110,6 +110,17 @@ struct Colors: ParsableCommand {
}
}
// If an extension need to be generated, ensure extensionOutputPath is defined
if options.extensionName != nil ||
options.extensionNameUIKit != nil {
guard let extensionOutputPath = options.extensionOutputPath,
extensionOutputPath.isEmpty == false else {
let error = ColorsToolError.missingExtensionPath
print(error.description)
Self.exit(withError: error)
}
}
// Check if needed to regenerate
let fileToCompareToInput: String = {
// If there is no extension file to compare

View File

@@ -17,6 +17,7 @@ enum ColorsToolError: Error {
case fileNotExists(String)
case badColorDefinition(String, String)
case deleteExistingColors(String)
case missingExtensionPath
var description: String {
switch self {
@@ -43,6 +44,9 @@ enum ColorsToolError: Error {
case .deleteExistingColors(let assetsFolder):
return "error: [\(Colors.toolName)] An error occured while deleting colors folder `\(assetsFolder)`"
case .missingExtensionPath:
return "error: [\(Colors.toolName)] Extension need to be generated but no `extensionOutputPath` is provided"
}
}
}

View File

@@ -24,12 +24,12 @@ struct ColorsToolOptions: ParsableArguments {
@Option(help: "Path of xcassets where to generate colors", transform: { $0.replaceTiltWithHomeDirectoryPath() })
var xcassetsPath: String
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
var extensionOutputPath: String
@Option(help: "Tell if it will generate static properties or not")
var staticMembers: Bool = false
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
var extensionOutputPath: String?
@Option(help: "Extension name. If not specified, no extension will be generated.")
var extensionName: String?
@@ -56,7 +56,7 @@ extension ColorsToolOptions {
}
var extensionFilePath: String? {
guard let extensionFileName else { return nil }
guard let extensionOutputPath, let extensionFileName else { return nil }
return "\(extensionOutputPath)/\(extensionFileName)"
}
@@ -73,7 +73,7 @@ extension ColorsToolOptions {
}
var extensionFilePathUIKit: String? {
guard let extensionFileNameUIKit else { return nil }
guard let extensionOutputPath, let extensionFileNameUIKit else { return nil }
return "\(extensionOutputPath)/\(extensionFileNameUIKit)"
}

View File

@@ -131,7 +131,7 @@ struct ColorsConfiguration: Codable, CustomDebugStringConvertible {
let inputFile: String
let style: String
let xcassetsPath: String
let extensionOutputPath: String
let extensionOutputPath: String?
let extensionName: String?
let extensionNameUIKit: String?
let extensionSuffix: String?
@@ -148,7 +148,7 @@ struct ColorsConfiguration: Codable, CustomDebugStringConvertible {
inputFile: String,
style: String,
xcassetsPath: String,
extensionOutputPath: String,
extensionOutputPath: String?,
extensionName: String?,
extensionNameUIKit: String?,
extensionSuffix: String?,
@@ -170,7 +170,7 @@ struct ColorsConfiguration: Codable, CustomDebugStringConvertible {
- Input file: \(inputFile)
- Style: \(style)
- Xcassets path: \(xcassetsPath)
- Extension output path: \(extensionOutputPath)
- Extension output path: \(extensionOutputPath ?? "-")
- Extension name: \(extensionName ?? "-")
- Extension name UIKit: \(extensionNameUIKit ?? "-")
- Extension suffix: \(extensionSuffix ?? "-")
@@ -230,7 +230,7 @@ struct ImagesConfiguration: Codable, CustomDebugStringConvertible {
let inputFile: String
let xcassetsPath: String
let extensionOutputPath: String
let extensionOutputPath: String?
let extensionName: String?
let extensionNameUIKit: String?
let extensionSuffix: String?
@@ -246,7 +246,7 @@ struct ImagesConfiguration: Codable, CustomDebugStringConvertible {
internal init(
inputFile: String,
xcassetsPath: String,
extensionOutputPath: String,
extensionOutputPath: String?,
extensionName: String?,
extensionNameUIKit: String?,
extensionSuffix: String?,
@@ -266,7 +266,7 @@ struct ImagesConfiguration: Codable, CustomDebugStringConvertible {
Images configuration:
- Input file: \(inputFile)
- Xcassets path: \(xcassetsPath)
- Extension output path: \(extensionOutputPath)
- Extension output path: \(extensionOutputPath ?? "-")
- Extension name: \(extensionName ?? "-")
- Extension name UIKit: \(extensionNameUIKit ?? "-")
- Extension suffix: \(extensionSuffix ?? "-")

View File

@@ -27,29 +27,23 @@ extension ColorsConfiguration: Runnable {
style,
"--xcassets-path",
xcassetsPath.prependIfRelativePath(projectDirectory),
"--extension-output-path",
extensionOutputPath.prependIfRelativePath(projectDirectory),
"--static-members",
"\(staticMembersOptions)"
]
if let extensionName {
args += [
"--extension-name",
extensionName
]
}
if let extensionNameUIKit {
args += [
"--extension-name-ui-kit",
extensionNameUIKit
]
}
if let extensionSuffix {
args += [
"--extension-suffix",
extensionSuffix
]
// Add optional parameters
[
("--extension-output-path", extensionOutputPath?.prependIfRelativePath(projectDirectory)),
("--extension-name", extensionName),
("--extension-name-ui-kit", extensionNameUIKit),
("--extension-suffix", extensionSuffix)
].forEach { argumentName, argumentValue in
if let argumentValue {
args += [
argumentName,
argumentValue
]
}
}
return args

View File

@@ -25,31 +25,23 @@ extension ImagesConfiguration: Runnable {
inputFile.prependIfRelativePath(projectDirectory),
"--xcassets-path",
xcassetsPath.prependIfRelativePath(projectDirectory),
"--extension-output-path",
extensionOutputPath.prependIfRelativePath(projectDirectory),
"--static-members",
"\(staticMembersOptions)"
]
if let extensionName {
args += [
"--extension-name",
extensionName
]
}
if let extensionNameUIKit {
args += [
"--extension-name-ui-kit",
extensionNameUIKit
]
}
if let extensionSuffix {
args += [
"--extension-suffix",
extensionSuffix
]
// Add optional parameters
[
("--extension-output-path", extensionOutputPath?.prependIfRelativePath(projectDirectory)),
("--extension-name", extensionName),
("--extension-name-ui-kit", extensionNameUIKit),
("--extension-suffix", extensionSuffix)
].forEach { argumentName, argumentValue in
if let argumentValue {
args += [
argumentName,
argumentValue
]
}
}
return args

View File

@@ -21,8 +21,6 @@ struct Images: ParsableCommand {
// MARK: - Static
static let toolName = "Images"
static let defaultExtensionName = "Image"
static let defaultExtensionNameUIKit = "UIImage"
// MARK: - Command Options
@@ -55,23 +53,29 @@ struct Images: ParsableCommand {
)
// Generate extension
ImageExtensionGenerator.generateExtensionFile(
images: imagesToGenerate,
staticVar: options.staticMembers,
inputFilename: options.inputFilenameWithoutExt,
extensionName: options.extensionName,
extensionFilePath: options.extensionFilePath,
isSwiftUI: true
)
if let extensionName = options.extensionName,
let extensionFilePath = options.extensionFilePath {
ImageExtensionGenerator.generateExtensionFile(
images: imagesToGenerate,
staticVar: options.staticMembers,
inputFilename: options.inputFilenameWithoutExt,
extensionName: extensionName,
extensionFilePath: extensionFilePath,
isSwiftUI: true
)
}
ImageExtensionGenerator.generateExtensionFile(
images: imagesToGenerate,
staticVar: options.staticMembers,
inputFilename: options.inputFilenameWithoutExt,
extensionName: options.extensionNameUIKit,
extensionFilePath: options.extensionFilePathUIKit,
isSwiftUI: false
)
if let extensionNameUIKit = options.extensionNameUIKit,
let extensionFilePathUIKit = options.extensionFilePathUIKit {
ImageExtensionGenerator.generateExtensionFile(
images: imagesToGenerate,
staticVar: options.staticMembers,
inputFilename: options.inputFilenameWithoutExt,
extensionName: extensionNameUIKit,
extensionFilePath: extensionFilePathUIKit,
isSwiftUI: false
)
}
print("[\(Self.toolName)] Images generated")
}
@@ -96,17 +100,39 @@ struct Images: ParsableCommand {
_ = Self.getSvgConverterPath()
// Extension for UIKit and SwiftUI should have different name
guard options.extensionName != options.extensionNameUIKit else {
let error = ImagesError.extensionNamesCollision(options.extensionName)
print(error.description)
Self.exit(withError: error)
if let extensionName = options.extensionName,
let extensionNameUIKit = options.extensionNameUIKit {
guard extensionName != extensionNameUIKit else {
let error = ImagesError.extensionNamesCollision(extensionName)
print(error.description)
Self.exit(withError: error)
}
}
// If an extension need to be generated, ensure extensionOutputPath is defined
if options.extensionName != nil ||
options.extensionNameUIKit != nil {
guard let extensionOutputPath = options.extensionOutputPath,
extensionOutputPath.isEmpty == false else {
let error = ImagesError.missingExtensionPath
print(error.description)
Self.exit(withError: error)
}
}
// Check if needed to regenerate
let fileToCompareToInput: String = {
// If there is no extension file to compare
// Then check the xcassets file instead
if let extensionFilePath = options.extensionFilePath {
return extensionFilePath
}
return options.xcassetsPath
}()
guard GeneratorChecker.shouldGenerate(
force: options.forceExecution,
inputFilePath: options.inputFile,
extensionFilePath: options.extensionFilePath
extensionFilePath: fileToCompareToInput
) else {
print("[\(Self.toolName)] Images are already up to date :) ")
return false

View File

@@ -18,6 +18,7 @@ enum ImagesError: Error {
case magickConvertNotFound
case writeFile(String, String)
case createAssetFolder(String)
case missingExtensionPath
case unknown(String)
var description: String {
@@ -49,6 +50,9 @@ enum ImagesError: Error {
case .createAssetFolder(let folder):
return "error: [\(Colors.toolName)] An error occured while creating folder `\(folder)`"
case .missingExtensionPath:
return "error: [\(Colors.toolName)] Extension need to be generated but no `extensionOutputPath` is provided"
case .unknown(let errorDescription):
return "error: [\(Images.toolName)] Unknown error: \(errorDescription)"
}

View File

@@ -24,17 +24,17 @@ struct ImagesOptions: ParsableArguments {
@Option(help: "Xcassets path where to generate images.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
var xcassetsPath: String
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
var extensionOutputPath: String
@Option(help: "Tell if it will generate static properties or not")
var staticMembers: Bool = false
@Option(help: "Extension name. If not specified, it will generate an Image extension.")
var extensionName: String = Images.defaultExtensionName
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
var extensionOutputPath: String?
@Option(help: "Extension name. If not specified, it will generate an UIImage extension.")
var extensionNameUIKit: String = Images.defaultExtensionNameUIKit
@Option(help: "Extension name. If not specified, no extension will be generated.")
var extensionName: String?
@Option(help: "Extension name. If not specified, no extension will be generated.")
var extensionNameUIKit: String?
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+Image{extensionSuffix}.swift")
var extensionSuffix: String?
@@ -46,28 +46,36 @@ extension ImagesOptions {
// MARK: - SwiftUI
var extensionFileName: String {
var extensionFileName: String? {
guard let extensionName else { return nil }
if let extensionSuffix {
return "\(extensionName)+\(extensionSuffix).swift"
}
return "\(extensionName).swift"
}
var extensionFilePath: String {
"\(extensionOutputPath)/\(extensionFileName)"
var extensionFilePath: String? {
guard let extensionOutputPath, let extensionFileName else { return nil }
return "\(extensionOutputPath)/\(extensionFileName)"
}
// MARK: - UIKit
var extensionFileNameUIKit: String {
var extensionFileNameUIKit: String? {
guard let extensionNameUIKit else { return nil }
if let extensionSuffix {
return "\(extensionNameUIKit)+\(extensionSuffix).swift"
}
return "\(extensionNameUIKit).swift"
}
var extensionFilePathUIKit: String {
"\(extensionOutputPath)/\(extensionFileNameUIKit)"
var extensionFilePathUIKit: String? {
guard let extensionOutputPath, let extensionFileNameUIKit else { return nil }
return "\(extensionOutputPath)/\(extensionFileNameUIKit)"
}
// MARK: -