Optional generation of extension (R.xx)
Optional generation of Colors/Fonts/Images/Stringium extension Fix swiftlint warning
This commit is contained in:
@ -5,11 +5,14 @@
|
||||
// Created by Loris Perret on 08/12/2023.
|
||||
//
|
||||
|
||||
// CPD-OFF
|
||||
|
||||
import CoreVideo
|
||||
import Foundation
|
||||
import ToolCore
|
||||
|
||||
// Disabled cause it's a pain to handle in generated string
|
||||
// swiftlint:disable type_body_length
|
||||
|
||||
enum AnalyticsGenerator {
|
||||
|
||||
@ -89,48 +92,49 @@ enum AnalyticsGenerator {
|
||||
) -> String {
|
||||
"""
|
||||
// Generated by ResgenSwift.\(Analytics.toolName) \(ResgenSwiftVersion)
|
||||
|
||||
|
||||
\(Self.getImport(targets: targets))
|
||||
|
||||
|
||||
\(Self.getAnalyticsProtocol(targets: targets))
|
||||
|
||||
\(Self.getTrackerTypeEnum())
|
||||
|
||||
|
||||
\(Self.getTrackerTypeEnum(targets: targets))
|
||||
|
||||
// MARK: - Manager
|
||||
|
||||
class AnalyticsManager {
|
||||
|
||||
|
||||
static var shared = AnalyticsManager()
|
||||
|
||||
|
||||
private init() {}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
|
||||
var managers: [TrackerType: AnalyticsManagerProtocol] = [:]
|
||||
|
||||
|
||||
\(Self.getEnabledContent())
|
||||
|
||||
|
||||
\(Self.getAnalyticsProperties(targets: targets))
|
||||
|
||||
|
||||
\(Self.getPrivateLogFunction())
|
||||
"""
|
||||
}
|
||||
|
||||
private static func getTrackerTypeEnum() -> String {
|
||||
|
||||
private static func getTrackerTypeEnum(targets: [TrackerType]) -> String {
|
||||
var result: [String] = []
|
||||
TrackerType.allCases.forEach { type in
|
||||
targets.forEach { type in
|
||||
result.append(" case \(type)")
|
||||
}
|
||||
|
||||
|
||||
return """
|
||||
// MARK: - Traker Type
|
||||
|
||||
|
||||
enum TrackerType: CaseIterable {
|
||||
|
||||
\(result.joined(separator: "\n"))
|
||||
}
|
||||
"""
|
||||
}
|
||||
|
||||
|
||||
private static func getEnabledContent() -> String {
|
||||
"""
|
||||
private var isEnabled: Bool {
|
||||
@ -140,9 +144,9 @@ enum AnalyticsGenerator {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Methods
|
||||
|
||||
|
||||
// MARK: - Enable Methods
|
||||
|
||||
private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) {
|
||||
managers.forEach { (key, value) in
|
||||
if analytics.contains(where: { type in
|
||||
@ -152,11 +156,11 @@ enum AnalyticsGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func enableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
|
||||
setAnalytics(enable: true, analytics)
|
||||
}
|
||||
|
||||
|
||||
func disableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
|
||||
setAnalytics(enable: false, analytics)
|
||||
}
|
||||
@ -171,6 +175,7 @@ enum AnalyticsGenerator {
|
||||
if targets.contains(TrackerType.matomo) {
|
||||
result.append("import MatomoTracker")
|
||||
}
|
||||
|
||||
if targets.contains(TrackerType.firebase) {
|
||||
result.append("import FirebaseAnalytics")
|
||||
}
|
||||
@ -180,13 +185,15 @@ enum AnalyticsGenerator {
|
||||
|
||||
private static func getPrivateLogFunction() -> String {
|
||||
"""
|
||||
private func logScreen(
|
||||
// MARK: - Private Log Methods
|
||||
|
||||
private func logScreen(
|
||||
name: String,
|
||||
path: String,
|
||||
params: [String: Any]?
|
||||
) {
|
||||
guard isEnabled else { return }
|
||||
|
||||
|
||||
managers.values.forEach { manager in
|
||||
manager.logScreen(
|
||||
name: name,
|
||||
@ -203,7 +210,7 @@ enum AnalyticsGenerator {
|
||||
params: [String: Any]?
|
||||
) {
|
||||
guard isEnabled else { return }
|
||||
|
||||
|
||||
managers.values.forEach { manager in
|
||||
manager.logEvent(
|
||||
name: name,
|
||||
@ -235,6 +242,7 @@ enum AnalyticsGenerator {
|
||||
)
|
||||
""")
|
||||
}
|
||||
|
||||
if targets.contains(TrackerType.firebase) {
|
||||
content.append(" managers[TrackerType.firebase] = FirebaseAnalyticsManager()")
|
||||
}
|
||||
@ -252,22 +260,22 @@ enum AnalyticsGenerator {
|
||||
// MARK: - Protocol
|
||||
|
||||
protocol AnalyticsManagerProtocol {
|
||||
|
||||
func logScreen(
|
||||
name: String,
|
||||
path: String,
|
||||
params: [String: Any]?
|
||||
)
|
||||
|
||||
|
||||
func logEvent(
|
||||
name: String,
|
||||
action: String,
|
||||
category: String,
|
||||
params: [String: Any]?
|
||||
)
|
||||
|
||||
|
||||
func setEnable(_ enable: Bool)
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
var result: [String] = [proto]
|
||||
@ -280,7 +288,7 @@ enum AnalyticsGenerator {
|
||||
result.append(FirebaseGenerator.service)
|
||||
}
|
||||
|
||||
return result.joined(separator: "\n")
|
||||
return result.joined(separator: "\n\n")
|
||||
}
|
||||
|
||||
private static func getProperties(
|
||||
@ -319,3 +327,5 @@ enum AnalyticsGenerator {
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
// CPD-ON
|
||||
|
@ -13,11 +13,11 @@ enum FirebaseGenerator {
|
||||
|
||||
static var service: String {
|
||||
[
|
||||
FirebaseGenerator.header,
|
||||
FirebaseGenerator.logScreen,
|
||||
FirebaseGenerator.logEvent,
|
||||
FirebaseGenerator.enable,
|
||||
FirebaseGenerator.footer
|
||||
Self.header,
|
||||
Self.logScreen,
|
||||
Self.logEvent,
|
||||
Self.enable,
|
||||
Self.footer
|
||||
]
|
||||
.joined(separator: "\n")
|
||||
}
|
||||
@ -29,6 +29,9 @@ enum FirebaseGenerator {
|
||||
// MARK: - Firebase
|
||||
|
||||
class FirebaseAnalyticsManager: AnalyticsManagerProtocol {
|
||||
|
||||
// MARK: - Methods
|
||||
|
||||
"""
|
||||
}
|
||||
|
||||
@ -42,11 +45,11 @@ enum FirebaseGenerator {
|
||||
var parameters = [
|
||||
AnalyticsParameterScreenName: name as NSObject
|
||||
]
|
||||
|
||||
|
||||
if path.isEmpty == false {
|
||||
parameters["path"] = path + "/iOS" as NSObject
|
||||
}
|
||||
|
||||
|
||||
if let supplementaryParameters = params {
|
||||
for (newKey, newValue) in supplementaryParameters {
|
||||
if parameters.contains(where: { (key: String, value: NSObject) in
|
||||
@ -54,11 +57,11 @@ enum FirebaseGenerator {
|
||||
}) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
parameters[newKey] = newValue as? NSObject
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Analytics.logEvent(
|
||||
AnalyticsEventScreenView,
|
||||
parameters: parameters
|
||||
@ -79,15 +82,15 @@ enum FirebaseGenerator {
|
||||
var parameters: [String:NSObject] = [
|
||||
AnalyticsParameterItemName: name.replacingOccurrences(of: " ", with: "_") as NSObject
|
||||
]
|
||||
|
||||
|
||||
if category.isEmpty == false {
|
||||
parameters["AnalyticsParameterItemCategory"] = category as NSObject
|
||||
}
|
||||
|
||||
|
||||
if action.isEmpty == false {
|
||||
parameters["action"] = action as NSObject
|
||||
}
|
||||
|
||||
|
||||
if let supplementaryParameters = params {
|
||||
for (newKey, newValue) in supplementaryParameters {
|
||||
if parameters.contains(where: { (key: String, value: NSObject) in
|
||||
@ -105,9 +108,10 @@ enum FirebaseGenerator {
|
||||
parameters: parameters
|
||||
)
|
||||
}
|
||||
|
||||
"""
|
||||
}
|
||||
|
||||
|
||||
private static var enable: String {
|
||||
"""
|
||||
func setEnable(_ enable: Bool) {
|
||||
@ -115,11 +119,10 @@ enum FirebaseGenerator {
|
||||
}
|
||||
"""
|
||||
}
|
||||
|
||||
|
||||
private static var footer: String {
|
||||
"""
|
||||
}
|
||||
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
@ -5,18 +5,20 @@
|
||||
// Created by Loris Perret on 05/12/2023.
|
||||
//
|
||||
|
||||
// CPD-OFF
|
||||
|
||||
import Foundation
|
||||
|
||||
enum MatomoGenerator {
|
||||
|
||||
static var service: String {
|
||||
[
|
||||
MatomoGenerator.header,
|
||||
MatomoGenerator.setup,
|
||||
MatomoGenerator.logScreen,
|
||||
MatomoGenerator.logEvent,
|
||||
MatomoGenerator.enable,
|
||||
MatomoGenerator.footer
|
||||
Self.header,
|
||||
Self.setup,
|
||||
Self.logScreen,
|
||||
Self.logEvent,
|
||||
Self.enable,
|
||||
Self.footer
|
||||
]
|
||||
.joined(separator: "\n")
|
||||
}
|
||||
@ -100,10 +102,10 @@ enum MatomoGenerator {
|
||||
url: nil
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
"""
|
||||
}
|
||||
|
||||
|
||||
private static var enable: String {
|
||||
"""
|
||||
func setEnable(_ enable: Bool) {
|
||||
@ -115,7 +117,8 @@ enum MatomoGenerator {
|
||||
private static var footer: String {
|
||||
"""
|
||||
}
|
||||
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
// CPD-ON
|
||||
|
@ -52,20 +52,22 @@ class AnalyticsDefinition {
|
||||
|
||||
private func getParameters() -> String {
|
||||
var result: String
|
||||
|
||||
|
||||
let paramsString = parameters.compactMap { parameter -> String? in
|
||||
guard parameter.value.isEmpty else { return nil }
|
||||
|
||||
|
||||
let defaultValue: String
|
||||
switch parameter.type {
|
||||
case .bool:
|
||||
defaultValue = "\(parameter.defaultValue.lowercased())"
|
||||
|
||||
case .int, .double:
|
||||
defaultValue = "\(parameter.defaultValue)"
|
||||
|
||||
case .string:
|
||||
defaultValue = "\"\(parameter.defaultValue)\""
|
||||
}
|
||||
|
||||
|
||||
let defaultValueString = parameter.defaultValue.isEmpty ? "" : " = \(defaultValue)"
|
||||
return "\(parameter.name): \(parameter.type.rawValue)\(defaultValueString)"
|
||||
}
|
||||
@ -90,9 +92,13 @@ class AnalyticsDefinition {
|
||||
for rep in parameter.replaceIn {
|
||||
switch rep {
|
||||
case "name": name = name.replacingFirstOccurrence(of: "_\(parameter.name.uppercased())_", with: "\\(\(parameter.name))")
|
||||
|
||||
case "path": path = path.replacingFirstOccurrence(of: "_\(parameter.name.uppercased())_", with: "\\(\(parameter.name))")
|
||||
|
||||
case "category": category = category.replacingFirstOccurrence(of: "_\(parameter.name.uppercased())_", with: "\\(\(parameter.name))")
|
||||
|
||||
case "action": action = action.replacingFirstOccurrence(of: "_\(parameter.name.uppercased())_", with: "\\(\(parameter.name))")
|
||||
|
||||
default:
|
||||
if let param = parameters.first(where: { $0.name == rep }), param.value.isEmpty == false {
|
||||
param.value = param.value.replacingFirstOccurrence(of: "_\(parameter.name.uppercased())_", with: "\\(\(parameter.name))")
|
||||
@ -117,8 +123,10 @@ class AnalyticsDefinition {
|
||||
switch param.type {
|
||||
case .bool:
|
||||
params.append("\"\(param.name)\": \(param.value.lowercased())")
|
||||
|
||||
case .int, .double:
|
||||
params.append("\"\(param.name)\": \(param.value)")
|
||||
|
||||
case .string:
|
||||
params.append("\"\(param.name)\": \"\(param.value)\"")
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class AnalyticsParameter {
|
||||
var replaceIn: [String] = []
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
|
||||
init(name: String, type: ParameterType, value: String, defaultValue: String) {
|
||||
self.name = name
|
||||
self.type = type
|
||||
|
@ -8,6 +8,7 @@
|
||||
import Foundation
|
||||
|
||||
enum ParameterType: String {
|
||||
|
||||
case string = "String"
|
||||
case int = "Int"
|
||||
case double = "Double"
|
||||
|
@ -70,7 +70,7 @@ class AnalyticsFileParser {
|
||||
private static func getParameters(from parameters: [AnalyticsParameterDTO]) -> [AnalyticsParameter] {
|
||||
func verify(value: String?, for type: ParameterType) {
|
||||
guard let value, value.isEmpty == false else { return }
|
||||
|
||||
|
||||
switch type {
|
||||
case .int:
|
||||
if Int(value) == nil {
|
||||
@ -78,23 +78,26 @@ class AnalyticsFileParser {
|
||||
print(error.description)
|
||||
Analytics.exit(withError: error)
|
||||
}
|
||||
|
||||
case .bool:
|
||||
if Bool(value.lowercased()) == nil {
|
||||
let error = AnalyticsError.invalidParameter("type of \(value) is not \(type)")
|
||||
print(error.description)
|
||||
Analytics.exit(withError: error)
|
||||
}
|
||||
|
||||
case .double:
|
||||
if Double(value) == nil {
|
||||
let error = AnalyticsError.invalidParameter("type of \(value) is not \(type)")
|
||||
print(error.description)
|
||||
Analytics.exit(withError: error)
|
||||
}
|
||||
|
||||
case .string:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return parameters.map { dtoParameter in
|
||||
// Type
|
||||
let type = dtoParameter.type.uppercasedFirst()
|
||||
@ -104,13 +107,13 @@ class AnalyticsFileParser {
|
||||
print(error.description)
|
||||
Analytics.exit(withError: error)
|
||||
}
|
||||
|
||||
|
||||
if dtoParameter.value != nil, dtoParameter.replaceIn != nil {
|
||||
let error = AnalyticsError.invalidParameter("you can't set 'value' and 'replaceIn' for \(dtoParameter.name)")
|
||||
print(error.description)
|
||||
Analytics.exit(withError: error)
|
||||
}
|
||||
|
||||
|
||||
verify(value: dtoParameter.value, for: typeEnum)
|
||||
verify(value: dtoParameter.defaultValue, for: typeEnum)
|
||||
|
||||
@ -147,7 +150,7 @@ class AnalyticsFileParser {
|
||||
}
|
||||
|
||||
if let parameters {
|
||||
definition.parameters = AnalyticsFileParser.getParameters(from: parameters)
|
||||
definition.parameters = Self.getParameters(from: parameters)
|
||||
}
|
||||
|
||||
return definition
|
||||
@ -215,7 +218,7 @@ class AnalyticsFileParser {
|
||||
if let category = event.category {
|
||||
definition.category = category
|
||||
}
|
||||
|
||||
|
||||
if let action = event.action {
|
||||
definition.action = action
|
||||
}
|
||||
|
@ -21,8 +21,6 @@ struct Colors: ParsableCommand {
|
||||
// MARK: - Static
|
||||
|
||||
static let toolName = "Color"
|
||||
static let defaultExtensionName = "Color"
|
||||
static let defaultExtensionNameUIKit = "UIColor"
|
||||
static let assetsColorsFolderName = "Colors"
|
||||
|
||||
// MARK: - Command options
|
||||
@ -57,22 +55,28 @@ struct Colors: ParsableCommand {
|
||||
// -> Time: 3.4505380392074585 seconds
|
||||
|
||||
// Generate extension
|
||||
ColorExtensionGenerator.writeExtensionFile(
|
||||
colors: parsedColors,
|
||||
staticVar: options.staticMembers,
|
||||
extensionName: options.extensionName,
|
||||
extensionFilePath: options.extensionFilePath,
|
||||
isSwiftUI: true
|
||||
)
|
||||
if let extensionName = options.extensionName,
|
||||
let extensionFilePath = options.extensionFilePath {
|
||||
ColorExtensionGenerator.writeExtensionFile(
|
||||
colors: parsedColors,
|
||||
staticVar: options.staticMembers,
|
||||
extensionName: extensionName,
|
||||
extensionFilePath: extensionFilePath,
|
||||
isSwiftUI: true
|
||||
)
|
||||
}
|
||||
|
||||
// Generate extension
|
||||
ColorExtensionGenerator.writeExtensionFile(
|
||||
colors: parsedColors,
|
||||
staticVar: options.staticMembers,
|
||||
extensionName: options.extensionNameUIKit,
|
||||
extensionFilePath: options.extensionFilePathUIKit,
|
||||
isSwiftUI: false
|
||||
)
|
||||
if let extensionNameUIKit = options.extensionNameUIKit,
|
||||
let extensionFilePathUIKit = options.extensionFilePathUIKit {
|
||||
ColorExtensionGenerator.writeExtensionFile(
|
||||
colors: parsedColors,
|
||||
staticVar: options.staticMembers,
|
||||
extensionName: extensionNameUIKit,
|
||||
extensionFilePath: extensionFilePathUIKit,
|
||||
isSwiftUI: false
|
||||
)
|
||||
}
|
||||
|
||||
print("[\(Self.toolName)] Colors generated")
|
||||
}
|
||||
@ -96,18 +100,40 @@ struct Colors: ParsableCommand {
|
||||
Self.exit(withError: error)
|
||||
}
|
||||
|
||||
// Extension for UIKit and SwiftUI should have different name
|
||||
guard options.extensionName != options.extensionNameUIKit else {
|
||||
let error = ColorsToolError.extensionNamesCollision(options.extensionName)
|
||||
print(error.description)
|
||||
Self.exit(withError: error)
|
||||
// Extension for UIKit and SwiftUI should have different name (if both are defined)
|
||||
if let extensionName = options.extensionName,
|
||||
let extensionNameUIKit = options.extensionNameUIKit {
|
||||
guard extensionName != extensionNameUIKit else {
|
||||
let error = ColorsToolError.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 = 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
|
||||
// Then check the xcassets file instead
|
||||
if let extensionFilePath = options.extensionFilePath {
|
||||
return extensionFilePath
|
||||
}
|
||||
return options.xcassetsPath
|
||||
}()
|
||||
guard GeneratorChecker.shouldGenerate(
|
||||
force: options.forceGeneration,
|
||||
inputFilePath: options.inputFile,
|
||||
extensionFilePath: options.extensionFilePath
|
||||
extensionFilePath: fileToCompareToInput
|
||||
) else {
|
||||
print("[\(Self.toolName)] Colors are already up to date :) ")
|
||||
return false
|
||||
|
@ -17,11 +17,12 @@ enum ColorsToolError: Error {
|
||||
case fileNotExists(String)
|
||||
case badColorDefinition(String, String)
|
||||
case deleteExistingColors(String)
|
||||
case missingExtensionPath
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .extensionNamesCollision(let extensionName):
|
||||
return "error: [\(Fonts.toolName)] Error on extension names, extension name and SwiftUI extension name should be different (\(extensionName) is used on both)"
|
||||
return "error: [\(Colors.toolName)] Error on extension names, extension name and SwiftUI extension name should be different (\(extensionName) is used on both)"
|
||||
|
||||
case .badFormat(let info):
|
||||
return "error: [\(Colors.toolName)] Bad line format: \(info). Accepted format are: colorName=\"#RGB/#ARGB\"; colorName \"#RGB/#ARGB\"; colorName \"#RGB/#ARGB\" \"#RGB/#ARGB\""
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,17 +24,17 @@ 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: "Extension name. If not specified, it will generate an Color extension.")
|
||||
var extensionName: String = Colors.defaultExtensionName
|
||||
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||
var extensionOutputPath: String?
|
||||
|
||||
@Option(help: "SwiftUI Extension name. If not specified, it will generate an UIColor extension.")
|
||||
var extensionNameUIKit: String = Colors.defaultExtensionNameUIKit
|
||||
@Option(help: "SwiftUI extension name. If not specified, no extension will be generated.")
|
||||
var extensionName: String?
|
||||
|
||||
@Option(help: "UIKit extension name. If not specified, no extension will be generated.")
|
||||
var extensionNameUIKit: String?
|
||||
|
||||
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+ColorsMyApp.swift")
|
||||
var extensionSuffix: String?
|
||||
@ -46,27 +46,35 @@ extension ColorsToolOptions {
|
||||
|
||||
// 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)"
|
||||
}
|
||||
}
|
||||
|
@ -18,20 +18,20 @@ struct FontsOptions: ParsableArguments {
|
||||
@Argument(help: "Input files where fonts ared defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||
var inputFile: 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 methods")
|
||||
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, it will generate an Font extension.")
|
||||
var extensionName: String = Fonts.defaultExtensionName
|
||||
|
||||
@Option(help: "Extension name. If not specified, it will generate an UIFont extension.")
|
||||
var extensionNameUIKit: String = Fonts.defaultExtensionNameUIKit
|
||||
@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}+FontsMyApp.swift")
|
||||
var extensionSuffix: String = ""
|
||||
var extensionSuffix: String?
|
||||
|
||||
@Option(name: .customLong("info-plist-paths"), help: "Info.plist paths (array). Will be used to update UIAppFonts content")
|
||||
fileprivate var infoPlistPathsRaw: String = ""
|
||||
@ -44,7 +44,7 @@ extension FontsOptions {
|
||||
// MARK: - SwiftUI
|
||||
|
||||
var extensionFileName: String {
|
||||
if extensionSuffix.isEmpty == false {
|
||||
if let extensionSuffix {
|
||||
return "\(extensionName)+\(extensionSuffix).swift"
|
||||
}
|
||||
return "\(extensionName).swift"
|
||||
@ -56,15 +56,19 @@ extension FontsOptions {
|
||||
|
||||
// MARK: - UIKit
|
||||
|
||||
var extensionFileNameUIKit: String {
|
||||
if extensionSuffix.isEmpty == false {
|
||||
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 extensionFileNameUIKit else { return nil }
|
||||
|
||||
return "\(extensionOutputPath)/\(extensionFileNameUIKit)"
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
@ -22,7 +22,6 @@ struct Fonts: ParsableCommand {
|
||||
|
||||
static let toolName = "Fonts"
|
||||
static let defaultExtensionName = "Font"
|
||||
static let defaultExtensionNameUIKit = "UIFont"
|
||||
|
||||
// MARK: - Command Options
|
||||
|
||||
@ -61,16 +60,25 @@ struct Fonts: ParsableCommand {
|
||||
isSwiftUI: true
|
||||
)
|
||||
|
||||
FontExtensionGenerator.writeExtensionFile(
|
||||
fontsNames: fontsNames,
|
||||
staticVar: options.staticMembers,
|
||||
extensionName: options.extensionNameUIKit,
|
||||
extensionFilePath: options.extensionFilePathUIKit,
|
||||
isSwiftUI: false
|
||||
)
|
||||
if let extensionNameUIKit = options.extensionNameUIKit,
|
||||
let extensionFilePathUIKit = options.extensionFilePathUIKit {
|
||||
FontExtensionGenerator.writeExtensionFile(
|
||||
fontsNames: fontsNames,
|
||||
staticVar: options.staticMembers,
|
||||
extensionName: extensionNameUIKit,
|
||||
extensionFilePath: extensionFilePathUIKit,
|
||||
isSwiftUI: false
|
||||
)
|
||||
}
|
||||
|
||||
print("Info.plist has been updated with:")
|
||||
print("\(FontPlistGenerator.generatePlistUIAppsFontContent(for: fontsNames, infoPlistPaths: options.infoPlistPaths))")
|
||||
if options.infoPlistPaths.isEmpty == false {
|
||||
let plistUpdateFontsData = FontPlistGenerator.generatePlistUIAppsFontContent(
|
||||
for: fontsNames,
|
||||
infoPlistPaths: options.infoPlistPaths
|
||||
)
|
||||
print("Info.plist has been updated with:")
|
||||
print(plistUpdateFontsData)
|
||||
}
|
||||
|
||||
print("[\(Self.toolName)] Fonts generated")
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ enum FontsToolError: Error {
|
||||
case inputFolderNotFound(String)
|
||||
case fileNotExists(String)
|
||||
case writeExtension(String, String)
|
||||
case missingExtensionPath
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
@ -31,6 +32,9 @@ enum FontsToolError: Error {
|
||||
|
||||
case let .writeExtension(filename, info):
|
||||
return "error: [\(Fonts.toolName)] An error occured while writing extension in \(filename): \(info)"
|
||||
|
||||
case .missingExtensionPath:
|
||||
return "error: [\(Fonts.toolName)] Extension need to be generated but no `extensionOutputPath` is provided"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 ?? "-")
|
||||
@ -181,7 +181,7 @@ struct ColorsConfiguration: Codable, CustomDebugStringConvertible {
|
||||
struct FontsConfiguration: Codable, CustomDebugStringConvertible {
|
||||
|
||||
let inputFile: String
|
||||
let extensionOutputPath: String
|
||||
let extensionOutputPath: String?
|
||||
let extensionName: String?
|
||||
let extensionNameUIKit: String?
|
||||
let extensionSuffix: String?
|
||||
@ -197,7 +197,7 @@ struct FontsConfiguration: Codable, CustomDebugStringConvertible {
|
||||
|
||||
internal init(
|
||||
inputFile: String,
|
||||
extensionOutputPath: String,
|
||||
extensionOutputPath: String?,
|
||||
extensionName: String?,
|
||||
extensionNameUIKit: String?,
|
||||
extensionSuffix: String?,
|
||||
@ -217,7 +217,7 @@ struct FontsConfiguration: Codable, CustomDebugStringConvertible {
|
||||
"""
|
||||
Fonts configuration:
|
||||
- Input file: \(inputFile)
|
||||
- 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 ?? "-")
|
||||
@ -280,7 +280,7 @@ struct StringsConfiguration: Codable, CustomDebugStringConvertible {
|
||||
let outputPath: String
|
||||
let langs: String
|
||||
let defaultLang: String
|
||||
let extensionOutputPath: String
|
||||
let extensionOutputPath: String?
|
||||
let extensionName: String?
|
||||
let extensionSuffix: String?
|
||||
private let staticMembers: Bool?
|
||||
@ -305,7 +305,7 @@ struct StringsConfiguration: Codable, CustomDebugStringConvertible {
|
||||
outputPath: String,
|
||||
langs: String,
|
||||
defaultLang: String,
|
||||
extensionOutputPath: String,
|
||||
extensionOutputPath: String?,
|
||||
extensionName: String?,
|
||||
extensionSuffix: String?,
|
||||
staticMembers: Bool?,
|
||||
@ -329,7 +329,7 @@ struct StringsConfiguration: Codable, CustomDebugStringConvertible {
|
||||
- Output path: \(outputPath)
|
||||
- Langs: \(langs)
|
||||
- Default lang: \(defaultLang)
|
||||
- Extension output path: \(extensionOutputPath)
|
||||
- Extension output path: \(extensionOutputPath ?? "-")
|
||||
- Extension name: \(extensionName ?? "-")
|
||||
- Extension suffix: \(extensionSuffix ?? "-")
|
||||
"""
|
||||
|
@ -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
|
||||
|
@ -23,32 +23,26 @@ extension FontsConfiguration: Runnable {
|
||||
|
||||
args += [
|
||||
inputFile.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
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// Add infoPlist paths
|
||||
if let infoPlistPaths {
|
||||
let adjustedPlistPaths = infoPlistPaths
|
||||
.split(separator: " ")
|
||||
|
@ -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
|
||||
|
@ -24,26 +24,24 @@ extension StringsConfiguration: Runnable {
|
||||
langs,
|
||||
"--default-lang",
|
||||
defaultLang,
|
||||
"--extension-output-path",
|
||||
extensionOutputPath.prependIfRelativePath(projectDirectory),
|
||||
"--static-members",
|
||||
"\(staticMembersOptions)",
|
||||
"--xc-strings",
|
||||
"\(xcStringsOptions)"
|
||||
]
|
||||
|
||||
if let extensionName {
|
||||
args += [
|
||||
"--extension-name",
|
||||
extensionName
|
||||
]
|
||||
}
|
||||
|
||||
if let extensionSuffix {
|
||||
args += [
|
||||
"--extension-suffix",
|
||||
extensionSuffix
|
||||
]
|
||||
// Add optional parameters
|
||||
[
|
||||
("--extension-output-path", extensionOutputPath?.prependIfRelativePath(projectDirectory)),
|
||||
("--extension-name", extensionName),
|
||||
("--extension-suffix", extensionSuffix)
|
||||
].forEach { argumentName, argumentValue in
|
||||
if let argumentValue {
|
||||
args += [
|
||||
argumentName,
|
||||
argumentValue
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Stringium.main(args)
|
||||
|
@ -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
|
||||
|
@ -18,12 +18,13 @@ enum ImagesError: Error {
|
||||
case magickConvertNotFound
|
||||
case writeFile(String, String)
|
||||
case createAssetFolder(String)
|
||||
case missingExtensionPath
|
||||
case unknown(String)
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .extensionNamesCollision(let extensionName):
|
||||
return "error: [\(Fonts.toolName)] Error on extension names, extension name and SwiftUI extension name should be different (\(extensionName) is used on both)"
|
||||
return "error: [\(Images.toolName)] Error on extension names, extension name and SwiftUI extension name should be different (\(extensionName) is used on both)"
|
||||
|
||||
case .inputFolderNotFound(let inputFolder):
|
||||
return "error: [\(Images.toolName)] Input folder not found: \(inputFolder)"
|
||||
@ -47,7 +48,10 @@ enum ImagesError: Error {
|
||||
return "error: [\(Images.toolName)] An error occured while writing content to \(filename): \(subErrorDescription)"
|
||||
|
||||
case .createAssetFolder(let folder):
|
||||
return "error: [\(Colors.toolName)] An error occured while creating folder `\(folder)`"
|
||||
return "error: [\(Images.toolName)] An error occured while creating folder `\(folder)`"
|
||||
|
||||
case .missingExtensionPath:
|
||||
return "error: [\(Images.toolName)] Extension need to be generated but no `extensionOutputPath` is provided"
|
||||
|
||||
case .unknown(let errorDescription):
|
||||
return "error: [\(Images.toolName)] Unknown error: \(errorDescription)"
|
||||
|
@ -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: "SwiftUI extension name. If not specified, no extension will be generated.")
|
||||
var extensionName: String?
|
||||
|
||||
@Option(help: "UIKit 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: -
|
||||
|
@ -19,8 +19,7 @@ enum StringsFileGenerator {
|
||||
langs: [String],
|
||||
defaultLang: String,
|
||||
tags: [String],
|
||||
outputPath: String,
|
||||
inputFilenameWithoutExt: String
|
||||
lprojPathFormat: String
|
||||
) {
|
||||
|
||||
var stringsFilesContent = [String: String]()
|
||||
@ -37,7 +36,7 @@ enum StringsFileGenerator {
|
||||
langs.forEach { lang in
|
||||
guard let fileContent = stringsFilesContent[lang] else { return }
|
||||
|
||||
let stringsFilePath = "\(outputPath)/\(lang).lproj/\(inputFilenameWithoutExt).strings"
|
||||
let stringsFilePath = String(format: lprojPathFormat, lang)
|
||||
let stringsFilePathURL = URL(fileURLWithPath: stringsFilePath)
|
||||
do {
|
||||
try fileContent.write(to: stringsFilePathURL, atomically: false, encoding: .utf8)
|
||||
@ -54,8 +53,7 @@ enum StringsFileGenerator {
|
||||
langs: [String],
|
||||
defaultLang: String,
|
||||
tags: [String],
|
||||
outputPath: String,
|
||||
inputFilenameWithoutExt: String
|
||||
xcStringsFilePath: String
|
||||
) {
|
||||
|
||||
let fileContent: String = Self.generateXcStringsFileContent(
|
||||
@ -65,12 +63,11 @@ enum StringsFileGenerator {
|
||||
sections: sections
|
||||
)
|
||||
|
||||
let stringsFilePath = "\(outputPath)/\(inputFilenameWithoutExt).xcstrings"
|
||||
let stringsFilePathURL = URL(fileURLWithPath: stringsFilePath)
|
||||
let stringsFilePathURL = URL(fileURLWithPath: xcStringsFilePath)
|
||||
do {
|
||||
try fileContent.write(to: stringsFilePathURL, atomically: false, encoding: .utf8)
|
||||
} catch {
|
||||
let error = StringiumError.writeFile(error.localizedDescription, stringsFilePath)
|
||||
let error = StringiumError.writeFile(error.localizedDescription, xcStringsFilePath)
|
||||
print(error.description)
|
||||
Stringium.exit(withError: error)
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ struct Stringium: ParsableCommand {
|
||||
// MARK: - Static
|
||||
|
||||
static let toolName = "Stringium"
|
||||
static let defaultExtensionName = "String"
|
||||
static let noTranslationTag: String = "notranslation"
|
||||
|
||||
// MARK: - Command options
|
||||
@ -49,8 +48,7 @@ struct Stringium: ParsableCommand {
|
||||
langs: options.langs,
|
||||
defaultLang: options.defaultLang,
|
||||
tags: options.tags,
|
||||
outputPath: options.stringsFileOutputPath,
|
||||
inputFilenameWithoutExt: options.inputFilenameWithoutExt
|
||||
lprojPathFormat: options.lprojPathFormat
|
||||
)
|
||||
} else {
|
||||
StringsFileGenerator.writeXcStringsFiles(
|
||||
@ -58,22 +56,25 @@ struct Stringium: ParsableCommand {
|
||||
langs: options.langs,
|
||||
defaultLang: options.defaultLang,
|
||||
tags: options.tags,
|
||||
outputPath: options.stringsFileOutputPath,
|
||||
inputFilenameWithoutExt: options.inputFilenameWithoutExt
|
||||
xcStringsFilePath: options.xcStringsFilePath
|
||||
)
|
||||
}
|
||||
|
||||
// Generate extension
|
||||
StringsFileGenerator.writeExtensionFiles(
|
||||
sections: sections,
|
||||
defaultLang: options.defaultLang,
|
||||
tags: options.tags,
|
||||
staticVar: options.staticMembers,
|
||||
inputFilename: options.inputFilenameWithoutExt,
|
||||
extensionName: options.extensionName,
|
||||
extensionFilePath: options.extensionFilePath,
|
||||
extensionSuffix: options.extensionSuffix
|
||||
)
|
||||
if let extensionName = options.extensionName,
|
||||
let extensionFilePath = options.extensionFilePath {
|
||||
print("Will generate extensions")
|
||||
StringsFileGenerator.writeExtensionFiles(
|
||||
sections: sections,
|
||||
defaultLang: options.defaultLang,
|
||||
tags: options.tags,
|
||||
staticVar: options.staticMembers,
|
||||
inputFilename: options.inputFilenameWithoutExt,
|
||||
extensionName: extensionName,
|
||||
extensionFilePath: extensionFilePath,
|
||||
extensionSuffix: options.extensionSuffix ?? ""
|
||||
)
|
||||
}
|
||||
|
||||
print("[\(Self.toolName)] Strings generated")
|
||||
}
|
||||
@ -104,10 +105,18 @@ struct Stringium: ParsableCommand {
|
||||
}
|
||||
|
||||
// Check if needed to regenerate
|
||||
let fileToCompareToInput: String = {
|
||||
// If there is no extension file to compare
|
||||
// Then check the xcassets file instead
|
||||
if options.xcStrings {
|
||||
return options.xcStringsFilePath
|
||||
}
|
||||
return String(format: options.lprojPathFormat, options.defaultLang)
|
||||
}()
|
||||
guard GeneratorChecker.shouldGenerate(
|
||||
force: options.forceGeneration,
|
||||
inputFilePath: options.inputFile,
|
||||
extensionFilePath: options.extensionFilePath
|
||||
extensionFilePath: fileToCompareToInput
|
||||
) else {
|
||||
print("[\(Self.toolName)] Strings are already up to date :) ")
|
||||
return false
|
||||
|
@ -15,35 +15,51 @@ struct StringiumOptions: ParsableArguments {
|
||||
@Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation")
|
||||
var forceGeneration = false
|
||||
|
||||
@Argument(help: "Input files where strings are defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||
@Argument(
|
||||
help: "Input files where strings are defined.",
|
||||
transform: { $0.replaceTiltWithHomeDirectoryPath() }
|
||||
)
|
||||
var inputFile: String
|
||||
|
||||
@Option(name: .customLong("output-path"), help: "Path where to strings file.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||
@Option(
|
||||
name: .customLong("output-path"),
|
||||
help: "Path where to strings file.",
|
||||
transform: { $0.replaceTiltWithHomeDirectoryPath() }
|
||||
)
|
||||
fileprivate var outputPathRaw: String
|
||||
|
||||
@Option(name: .customLong("langs"), help: "Langs to generate.")
|
||||
@Option(
|
||||
name: .customLong("langs"),
|
||||
help: "Langs to generate."
|
||||
)
|
||||
fileprivate var langsRaw: String
|
||||
|
||||
@Option(help: "Default langs.")
|
||||
var defaultLang: String
|
||||
|
||||
@Option(name: .customLong("tags"), help: "Tags to generate.")
|
||||
@Option(
|
||||
name: .customLong("tags"),
|
||||
help: "Tags to generate."
|
||||
)
|
||||
fileprivate var tagsRaw: String = "ios iosonly iosOnly notranslation"
|
||||
|
||||
@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")
|
||||
@Option(help: "Generate static properties. False by default")
|
||||
var staticMembers: Bool = false
|
||||
|
||||
@Option(help: "Tell if it will generate xcStrings file or not")
|
||||
var xcStrings: Bool = false
|
||||
@Option(help: "Tell if it will generate xcStrings file or lproj file. True by default")
|
||||
var xcStrings: Bool = true
|
||||
|
||||
@Option(help: "Extension name. If not specified, it will generate an String extension.")
|
||||
var extensionName: String = Stringium.defaultExtensionName
|
||||
@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?
|
||||
|
||||
@Option(help: "Extension suffix: {extensionName}+{extensionSuffix}.swift")
|
||||
var extensionSuffix: String
|
||||
var extensionSuffix: String?
|
||||
}
|
||||
|
||||
// MARK: - Private var getter
|
||||
@ -75,12 +91,21 @@ extension StringiumOptions {
|
||||
|
||||
extension StringiumOptions {
|
||||
|
||||
var extensionFileName: String {
|
||||
"\(extensionName)+\(extensionSuffix).swift"
|
||||
private var extensionFileName: String? {
|
||||
if let extensionName {
|
||||
if let extensionSuffix {
|
||||
return "\(extensionName)+\(extensionSuffix).swift"
|
||||
}
|
||||
return "\(extensionName).swift"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var extensionFilePath: String {
|
||||
"\(extensionOutputPath)/\(extensionFileName)"
|
||||
var extensionFilePath: String? {
|
||||
if let extensionOutputPath, let extensionFileName {
|
||||
return "\(extensionOutputPath)/\(extensionFileName)"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var inputFilenameWithoutExt: String {
|
||||
@ -88,4 +113,12 @@ extension StringiumOptions {
|
||||
.deletingPathExtension()
|
||||
.lastPathComponent
|
||||
}
|
||||
|
||||
var xcStringsFilePath: String {
|
||||
"\(stringsFileOutputPath)/\(inputFilenameWithoutExt).xcstrings"
|
||||
}
|
||||
|
||||
var lprojPathFormat: String {
|
||||
"\(stringsFileOutputPath)/%@.lproj/\(inputFilenameWithoutExt).strings"
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user