diff --git a/SampleFiles/Colors/Generated/UIColor+GenAllScript.swift b/SampleFiles/Colors/Generated/UIColor+GenAllScript.swift
index 43de86c..b86c911 100644
--- a/SampleFiles/Colors/Generated/UIColor+GenAllScript.swift
+++ b/SampleFiles/Colors/Generated/UIColor+GenAllScript.swift
@@ -1,4 +1,4 @@
-// Generated from ColorToolCore at 2022-07-22 15:38:00 +0000
+// Generated by ResgenSwift.ColorTool 1.0.0
import UIKit
diff --git a/SampleFiles/Fonts/Generated/UIFont+GenAllScript.swift b/SampleFiles/Fonts/Generated/UIFont+GenAllScript.swift
index 398823b..8ea97fa 100644
--- a/SampleFiles/Fonts/Generated/UIFont+GenAllScript.swift
+++ b/SampleFiles/Fonts/Generated/UIFont+GenAllScript.swift
@@ -1,4 +1,4 @@
-// Generated from FontToolCore
+// Generated by ResgenSwift.FontTool 1.0.0
import UIKit
@@ -19,44 +19,43 @@ extension UIFont {
// MARK: - Getter
- static let LatoItalic: ((_ size: CGFloat) -> UIFont) = { size in
- UIFont(name: FontName.LatoItalic.rawValue, size: size)!
- }
+ static let LatoItalic: ((_ size: CGFloat) -> UIFont) = { size in
+ UIFont(name: FontName.LatoItalic.rawValue, size: size)!
+ }
- static let LatoLightItalic: ((_ size: CGFloat) -> UIFont) = { size in
- UIFont(name: FontName.LatoLightItalic.rawValue, size: size)!
- }
+ static let LatoLightItalic: ((_ size: CGFloat) -> UIFont) = { size in
+ UIFont(name: FontName.LatoLightItalic.rawValue, size: size)!
+ }
- static let LatoHairline: ((_ size: CGFloat) -> UIFont) = { size in
- UIFont(name: FontName.LatoHairline.rawValue, size: size)!
- }
+ static let LatoHairline: ((_ size: CGFloat) -> UIFont) = { size in
+ UIFont(name: FontName.LatoHairline.rawValue, size: size)!
+ }
- static let LatoBold: ((_ size: CGFloat) -> UIFont) = { size in
- UIFont(name: FontName.LatoBold.rawValue, size: size)!
- }
+ static let LatoBold: ((_ size: CGFloat) -> UIFont) = { size in
+ UIFont(name: FontName.LatoBold.rawValue, size: size)!
+ }
- static let LatoBlack: ((_ size: CGFloat) -> UIFont) = { size in
- UIFont(name: FontName.LatoBlack.rawValue, size: size)!
- }
+ static let LatoBlack: ((_ size: CGFloat) -> UIFont) = { size in
+ UIFont(name: FontName.LatoBlack.rawValue, size: size)!
+ }
- static let LatoRegular: ((_ size: CGFloat) -> UIFont) = { size in
- UIFont(name: FontName.LatoRegular.rawValue, size: size)!
- }
+ static let LatoRegular: ((_ size: CGFloat) -> UIFont) = { size in
+ UIFont(name: FontName.LatoRegular.rawValue, size: size)!
+ }
- static let LatoBlackItalic: ((_ size: CGFloat) -> UIFont) = { size in
- UIFont(name: FontName.LatoBlackItalic.rawValue, size: size)!
- }
+ static let LatoBlackItalic: ((_ size: CGFloat) -> UIFont) = { size in
+ UIFont(name: FontName.LatoBlackItalic.rawValue, size: size)!
+ }
- static let LatoBoldItalic: ((_ size: CGFloat) -> UIFont) = { size in
- UIFont(name: FontName.LatoBoldItalic.rawValue, size: size)!
- }
+ static let LatoBoldItalic: ((_ size: CGFloat) -> UIFont) = { size in
+ UIFont(name: FontName.LatoBoldItalic.rawValue, size: size)!
+ }
- static let LatoLight: ((_ size: CGFloat) -> UIFont) = { size in
- UIFont(name: FontName.LatoLight.rawValue, size: size)!
- }
-
- static let LatoHairlineItalic: ((_ size: CGFloat) -> UIFont) = { size in
- UIFont(name: FontName.LatoHairlineItalic.rawValue, size: size)!
- }
+ static let LatoLight: ((_ size: CGFloat) -> UIFont) = { size in
+ UIFont(name: FontName.LatoLight.rawValue, size: size)!
+ }
+ static let LatoHairlineItalic: ((_ size: CGFloat) -> UIFont) = { size in
+ UIFont(name: FontName.LatoHairlineItalic.rawValue, size: size)!
+ }
}
\ No newline at end of file
diff --git a/SampleFiles/Images/Generated/UIImage+GenAllScript.swift b/SampleFiles/Images/Generated/UIImage+GenAllScript.swift
index 56f64d3..0d1bf02 100644
--- a/SampleFiles/Images/Generated/UIImage+GenAllScript.swift
+++ b/SampleFiles/Images/Generated/UIImage+GenAllScript.swift
@@ -1,4 +1,4 @@
-// Generated from Imagium at 2022-07-22 15:38:05 +0000
+// Generated by ResgenSwift.Imagium 1.0.0
// Images from sampleImages
import UIKit
diff --git a/SampleFiles/Strings/Generated/String+GenAllScript.swift b/SampleFiles/Strings/Generated/String+GenAllScript.swift
index 2538963..98cb8ef 100644
--- a/SampleFiles/Strings/Generated/String+GenAllScript.swift
+++ b/SampleFiles/Strings/Generated/String+GenAllScript.swift
@@ -1,4 +1,4 @@
-// Generated from Strings-Stringium at 2022-07-22 15:38:03 +0000
+// Generated by ResgenSwift.Strings.Stringium 1.0.0
import UIKit
diff --git a/SampleFiles/Tags/Generated/Tags+GenAllScript.swift b/SampleFiles/Tags/Generated/Tags+GenAllScript.swift
index 3a617c5..01fc191 100644
--- a/SampleFiles/Tags/Generated/Tags+GenAllScript.swift
+++ b/SampleFiles/Tags/Generated/Tags+GenAllScript.swift
@@ -1,4 +1,4 @@
-// Generated from Strings-Tags at 2022-07-22 15:38:04 +0000
+// Generated by ResgenSwift.Strings.Tags 1.0.0
// typelias Tags = String
diff --git a/Sources/ColorTool/ColorExtensionGenerator.swift b/Sources/ColorTool/ColorExtensionGenerator.swift
deleted file mode 100644
index 75e8442..0000000
--- a/Sources/ColorTool/ColorExtensionGenerator.swift
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// ColorExtensionGenerator.swift
-//
-//
-// Created by Thibaut Schmitt on 20/12/2021.
-//
-
-import Foundation
-import ToolCore
-
-struct ColorExtensionGenerator {
-
- let colors: [GenColor]
- let extensionClassname: String
- let isUIColorExtension: Bool
-
- func getHeader() -> String {
- """
- // Generated by ResgenSwift.ColorToolCore \(ResgenSwiftVersion)
-
- import UIKit
-
- extension \(extensionClassname) {\n
- """
- }
-
- func getFooter() -> String {
- """
- }
- """
- }
-
- func getProperties() -> String {
- colors.map {
- if extensionClassname == ColorTool.defaultExtensionName {
- return $0.getColorStaticProperty()
- }
- return $0.getColorProperty()
- }
- .joined(separator: "\n\n")
- }
-}
diff --git a/Sources/ColorTool/ColorToolOptions.swift b/Sources/ColorTool/ColorToolOptions.swift
index 0cda982..e0c6ee3 100644
--- a/Sources/ColorTool/ColorToolOptions.swift
+++ b/Sources/ColorTool/ColorToolOptions.swift
@@ -16,7 +16,7 @@ struct ColorToolOptions: ParsableArguments {
var inputFile: String
@Option(help: "Color style to generate: light for light colors only, or all for dark and light colors")
- var style: String
+ fileprivate var style: String
@Option(help: "Path of xcassets where to generate colors", transform: { $0.replaceTiltWithHomeDirectoryPath() })
var xcassetsPath: String
@@ -30,3 +30,9 @@ struct ColorToolOptions: ParsableArguments {
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+ColorsMyApp.swift")
var extensionSuffix: String = ""
}
+
+extension ColorToolOptions {
+ var colorStyle: ColorStyle {
+ ColorStyle(rawValue: style) ?? .all
+ }
+}
diff --git a/Sources/ColorTool/Generator/ColorExtensionGenerator.swift b/Sources/ColorTool/Generator/ColorExtensionGenerator.swift
new file mode 100644
index 0000000..9847900
--- /dev/null
+++ b/Sources/ColorTool/Generator/ColorExtensionGenerator.swift
@@ -0,0 +1,67 @@
+//
+// ColorExtensionGenerator.swift
+//
+//
+// Created by Thibaut Schmitt on 20/12/2021.
+//
+
+import Foundation
+import ToolCore
+
+struct ColorExtensionGenerator {
+
+ let colors: [ParsedColor]
+ let extensionClassname: String
+
+ static func writeExtensionFile(colors: [ParsedColor], staticVar: Bool, extensionName: String, extensionFilePath: String) {
+ // Create file if not exists
+ let fileManager = FileManager()
+ if fileManager.fileExists(atPath: extensionFilePath) == false {
+ Shell.shell("touch", "\(extensionFilePath)")
+ }
+
+ // Create extension content
+ let extensionContent = [
+ Self.getHeader(extensionClassname: extensionName),
+ Self.getProperties(for: colors, withStaticVar: staticVar),
+ Self.getFooter()
+ ]
+ .joined(separator: "\n")
+
+ // Write content
+ let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
+ do {
+ try extensionContent.write(to: extensionFilePathURL, atomically: true, encoding: .utf8)
+ } catch (let error) {
+ let error = ColorToolError.writeExtension(extensionFilePath, error.localizedDescription)
+ print(error.localizedDescription)
+ ColorTool.exit(withError: error)
+ }
+ }
+
+ private static func getHeader(extensionClassname: String) -> String {
+ """
+ // Generated by ResgenSwift.\(ColorTool.toolName) \(ResgenSwiftVersion)
+
+ import UIKit
+
+ extension \(extensionClassname) {\n
+ """
+ }
+
+ private static func getFooter() -> String {
+ """
+ }
+ """
+ }
+
+ private static func getProperties(for colors: [ParsedColor], withStaticVar staticVar: Bool) -> String {
+ colors.map {
+ if staticVar {
+ return $0.getColorStaticProperty()
+ }
+ return $0.getColorProperty()
+ }
+ .joined(separator: "\n\n")
+ }
+}
diff --git a/Sources/ColorTool/ColorXcassetHelper.swift b/Sources/ColorTool/Generator/ColorXcassetHelper.swift
similarity index 80%
rename from Sources/ColorTool/ColorXcassetHelper.swift
rename to Sources/ColorTool/Generator/ColorXcassetHelper.swift
index 6eb3191..1223e5e 100644
--- a/Sources/ColorTool/ColorXcassetHelper.swift
+++ b/Sources/ColorTool/Generator/ColorXcassetHelper.swift
@@ -10,17 +10,14 @@ import ToolCore
struct ColorXcassetHelper {
- let xcassetsPath: String
- let colors: [GenColor]
-
- func generateXcassetColors() {
+ static func generateXcassetColors(colors: [ParsedColor], to xcassetsPath: String) {
colors.forEach {
- generateColorSetAssets(from: $0)
+ Self.generateColorSetAssets(from: $0, to: xcassetsPath)
}
}
// Generate ColorSet in XCAssets file
- private func generateColorSetAssets(from color: GenColor) {
+ private static func generateColorSetAssets(from color: ParsedColor, to xcassetsPath: String) {
// Create ColorSet
let colorSetPath = "\(xcassetsPath)/Colors/\(color.name).colorset"
Shell.shell("mkdir", "-p", "\(colorSetPath)")
diff --git a/Sources/ColorTool/Model/ColorStyle.swift b/Sources/ColorTool/Model/ColorStyle.swift
new file mode 100644
index 0000000..aae3d97
--- /dev/null
+++ b/Sources/ColorTool/Model/ColorStyle.swift
@@ -0,0 +1,13 @@
+//
+// File.swift
+//
+//
+// Created by Thibaut Schmitt on 29/08/2022.
+//
+
+import Foundation
+
+enum ColorStyle: String, Decodable {
+ case light
+ case all
+}
diff --git a/Sources/ColorTool/GenColor.swift b/Sources/ColorTool/Model/GenColor.swift
similarity index 98%
rename from Sources/ColorTool/GenColor.swift
rename to Sources/ColorTool/Model/GenColor.swift
index 2258fb0..458f337 100644
--- a/Sources/ColorTool/GenColor.swift
+++ b/Sources/ColorTool/Model/GenColor.swift
@@ -1,5 +1,5 @@
//
-// GenColor.swift
+// ParsedColor.swift
//
//
// Created by Thibaut Schmitt on 20/12/2021.
@@ -7,7 +7,7 @@
import Foundation
-struct GenColor {
+struct ParsedColor {
let name: String
let light: String
let dark: String
diff --git a/Sources/ColorTool/Parser/ColorFileParser.swift b/Sources/ColorTool/Parser/ColorFileParser.swift
new file mode 100644
index 0000000..64f5a26
--- /dev/null
+++ b/Sources/ColorTool/Parser/ColorFileParser.swift
@@ -0,0 +1,49 @@
+//
+// File.swift
+//
+//
+// Created by Thibaut Schmitt on 29/08/2022.
+//
+
+import Foundation
+
+class ColorFileParser {
+ static func parse(_ inputFile: String, colorStyle: ColorStyle) -> [ParsedColor] {
+ // Get content of input file
+ let inputFileContent = try! String(contentsOfFile: inputFile, encoding: .utf8)
+ let colorsByLines = inputFileContent.components(separatedBy: CharacterSet.newlines)
+
+ // Iterate on each line of input file
+ return colorsByLines.enumerated().compactMap { lineNumber, colorLine in
+ // Required format:
+ // colorName="#RGB/#ARGB", colorName "#RGB/#ARGB", colorName "#RGB/#ARGB" "#RGB/#ARGB"
+ let colorLineCleanedUp = colorLine
+ .removeTrailingWhitespace()
+ .replacingOccurrences(of: "=", with: "") // Keep compat with current file format
+
+ guard colorLineCleanedUp.hasPrefix("#") == false, colorLineCleanedUp.isEmpty == false else {
+ print("[\(ColorTool.toolName)] ⚠️ BadFormat or empty line (line number: \(lineNumber + 1)). Skip this line")
+ return nil
+ }
+
+ let colorContent = colorLineCleanedUp.split(separator: " ")
+
+ guard colorContent.count >= 2 else {
+ let error = ColorToolError.badFormat(colorLine)
+ print(error.localizedDescription)
+ ColorTool.exit(withError: error)
+ }
+
+ switch colorStyle {
+ case .light:
+ return ParsedColor(name: String(colorContent[0]), light: String(colorContent[1]), dark: String(colorContent[1]))
+
+ case .all:
+ if colorContent.count == 3 {
+ return ParsedColor(name: String(colorContent[0]), light: String(colorContent[1]), dark: String(colorContent[2]))
+ }
+ return ParsedColor(name: String(colorContent[0]), light: String(colorContent[1]), dark: String(colorContent[1]))
+ }
+ }
+ }
+}
diff --git a/Sources/ColorTool/main.swift b/Sources/ColorTool/main.swift
index 246a865..4ab321c 100644
--- a/Sources/ColorTool/main.swift
+++ b/Sources/ColorTool/main.swift
@@ -9,134 +9,101 @@ import Foundation
import ToolCore
import ArgumentParser
-enum ColorStyle: String, Decodable {
- case light
- case all
-}
-
struct ColorTool: ParsableCommand {
+
+ // MARK: - CommandConfiguration
+
+ static var configuration = CommandConfiguration(
+ abstract: "A utility for generate colors assets and their getters.",
+ version: "0.1.0"
+ )
+
+ // MARK: - Static
+
+ static let toolName = "ColorTool"
static let defaultExtensionName = "UIColor"
static let assetsColorsFolderName = "Colors"
+ // MARK: - Properties
+
+ var extensionFileName: String {
+ if options.extensionSuffix.isEmpty == false {
+ return "\(options.extensionName)+\(options.extensionSuffix).swift"
+ }
+ return "\(options.extensionName).swift"
+ }
+ var extensionFilePath: String { "\(options.extensionOutputPath)/\(extensionFileName)" }
+ var generateStaticVariable: Bool {
+ options.extensionName == Self.defaultExtensionName
+ }
+
+ // MARK: - Command options
+
@OptionGroup var options: ColorToolOptions
- var colorStyle: ColorStyle { ColorStyle(rawValue: options.style) ?? .all }
- var extensionFileName: String { "\(options.extensionName)+\(options.extensionSuffix).swift" }
- var extensionFilePath: String { "\(options.extensionOutputPath)/\(extensionFileName)" }
+ // MARK: - Run
public func run() throws {
- print("[ColorTool] Starting colors generation")
-
- print("[ColorTool] Will use inputFile \(options.inputFile) to generate \(colorStyle) colors in xcassets \(options.xcassetsPath)")
- print("[ColorTool] Extension will be \(extensionFilePath)")
+ print("[\(Self.toolName)] Starting colors generation")
+ print("[\(Self.toolName)] Will use inputFile \(options.inputFile) to generate \(options.colorStyle) colors in xcassets \(options.xcassetsPath)")
// Check requirements
+ guard checkRequirements() else { return }
+
+ print("[\(Self.toolName)] Will generate colors")
+
+ // Delete current colors
+ deleteCurrentColors()
+
+ // Get colors to generate
+ let parsedColors = ColorFileParser.parse(options.inputFile,
+ colorStyle: options.colorStyle)
+
+ // Generate all colors in xcassets
+ ColorXcassetHelper.generateXcassetColors(colors: parsedColors,
+ to: options.xcassetsPath)
+
+ // Generate extension
+ ColorExtensionGenerator.writeExtensionFile(colors: parsedColors,
+ staticVar: generateStaticVariable,
+ extensionName: options.extensionName,
+ extensionFilePath: extensionFilePath)
+
+ print("[\(Self.toolName)] Colors generated")
+ }
+
+ // MARK: - Requirements
+
+ private func checkRequirements() -> Bool {
let fileManager = FileManager()
- guard fileManager.fileExists(atPath: options.xcassetsPath) else {
- let error = ColorToolError.fileNotExists(options.xcassetsPath)
- print(error.localizedDescription)
- ColorTool.exit(withError: error)
- }
+
+ // Check if input file exists
guard fileManager.fileExists(atPath: options.inputFile) else {
let error = ColorToolError.fileNotExists(options.inputFile)
print(error.localizedDescription)
ColorTool.exit(withError: error)
}
-
- // Check if needed to regenerate
- guard GeneratorChecker.shouldGenerate(force: options.forceGeneration, inputFilePath: options.inputFile, extensionFilePath: extensionFilePath) else {
- print("[ColorTool] Colors are already up to date :) ")
- return
- }
- print("[ColorTool] Will generate colors")
- // Delete current colors
- Shell.shell("rm", "-rf", "\(options.xcassetsPath)/Colors/*")
-
- // Get colors
- let colorsToGen = getColorsGen()
-
- // Generate all colors in xcassets
- let colorAssetHelper = ColorXcassetHelper(xcassetsPath: options.xcassetsPath, colors: colorsToGen)
- colorAssetHelper.generateXcassetColors()
-
- // Generate extension
- let extensionGenerator = ColorExtensionGenerator(colors: colorsToGen,
- extensionClassname: options.extensionName,
- isUIColorExtension: isUIColorExtension())
- let extensionHeader = extensionGenerator.getHeader()
- let extensionProperties = extensionGenerator.getProperties()
- let extensionFooter = extensionGenerator.getFooter()
-
- generateExtensionFile(extensionHeader, extensionProperties, extensionFooter)
-
- print("[ColorTool] Colors generated")
- }
-
- private func generateExtensionFile(_ args: String...) {
- // Create file if not exists
- let fileManager = FileManager()
- if fileManager.fileExists(atPath: extensionFilePath) == false {
- Shell.shell("touch", "\(extensionFilePath)")
- }
-
- // Create extension content
- let extensionContent = args.joined(separator: "\n")
-
- // Write content
- let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
- do {
- try extensionContent.write(to: extensionFilePathURL, atomically: true, encoding: .utf8)
- } catch (let error) {
- let error = ColorToolError.writeExtension(extensionFilePath, error.localizedDescription)
+ // Check if xcassets file exists
+ guard fileManager.fileExists(atPath: options.xcassetsPath) else {
+ let error = ColorToolError.fileNotExists(options.xcassetsPath)
print(error.localizedDescription)
ColorTool.exit(withError: error)
}
- }
-
- private func getColorsGen() -> [GenColor] {
- // Get content of input file
- let inputFileContent = try! String(contentsOfFile: options.inputFile, encoding: .utf8)
- let colorsByLines = inputFileContent.components(separatedBy: CharacterSet.newlines)
- // Iterate on each line of input file
- return colorsByLines.enumerated().compactMap { lineNumber, colorLine in
- // Required format:
- // colorName="#RGB/#ARGB", colorName "#RGB/#ARGB", colorName "#RGB/#ARGB" "#RGB/#ARGB"
- let colorLineCleanedUp = colorLine
- .removeTrailingWhitespace()
- .replacingOccurrences(of: "=", with: "") // Keep compat with current file format
-
- guard colorLineCleanedUp.hasPrefix("#") == false, colorLineCleanedUp.isEmpty == false else {
- print("[ColorTool] ⚠️ BadFormat or empty line (line number: \(lineNumber + 1)). Skip this line")
- return nil
- }
-
- let colorContent = colorLineCleanedUp.split(separator: " ")
-
- guard colorContent.count >= 2 else {
- let error = ColorToolError.badFormat(colorLine)
- print(error.localizedDescription)
- ColorTool.exit(withError: error)
- }
-
- switch colorStyle {
- case .light:
- return GenColor(name: String(colorContent[0]), light: String(colorContent[1]), dark: String(colorContent[1]))
-
- case .all:
- if colorContent.count == 3 {
- return GenColor(name: String(colorContent[0]), light: String(colorContent[1]), dark: String(colorContent[2]))
- }
- return GenColor(name: String(colorContent[0]), light: String(colorContent[1]), dark: String(colorContent[1]))
- }
+ // Check if needed to regenerate
+ guard GeneratorChecker.shouldGenerate(force: options.forceGeneration, inputFilePath: options.inputFile, extensionFilePath: extensionFilePath) else {
+ print("[\(Self.toolName)] Colors are already up to date :) ")
+ return false
}
+
+ return true
}
// MARK: - Helpers
- private func isUIColorExtension() -> Bool {
- options.extensionName == Self.defaultExtensionName
+ private func deleteCurrentColors() {
+ Shell.shell("rm", "-rf", "\(options.xcassetsPath)/Colors/*")
}
}
diff --git a/Sources/FontTool/FontToolContentGenerator.swift b/Sources/FontTool/FontToolContentGenerator.swift
deleted file mode 100644
index 5d82dba..0000000
--- a/Sources/FontTool/FontToolContentGenerator.swift
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// FontToolContentGenerator.swift
-//
-//
-// Created by Thibaut Schmitt on 13/12/2021.
-//
-
-import Foundation
-import ToolCore
-
-class FontToolContentGenerator {
-
- static func getExtensionHeader(fontsNames: [String]) -> String {
- """
- // Generated by ResgenSwift.FontToolCore \(ResgenSwiftVersion)
-
- import UIKit
-
- """
- }
-
- static func getFontNameEnum(fontsNames: [String]) -> String {
- var enumDefinition = "\tenum FontName: String {\n"
-
- fontsNames.forEach {
- //debugPrint("Name: \($0.removeCharacters(from: "[]+-_"))")
- enumDefinition += "\t\tcase \($0.removeCharacters(from: "[]+-_")) = \"\($0)\"\n"
- }
- enumDefinition += "\t}\n"
-
- return enumDefinition
- }
-
- static func getFontMethods(fontsNames: [String], isUIFontExtension: Bool) -> String {
- var methods = "\t// MARK: - Getter\n"
-
- fontsNames
- .unique()
- .forEach {
- let fontNameSanitize = $0.removeCharacters(from: "[]+-_")
-
- if isUIFontExtension {
- methods += """
- \n\tstatic let \(fontNameSanitize): ((_ size: CGFloat) -> UIFont) = { size in
- \tUIFont(name: FontName.\(fontNameSanitize).rawValue, size: size)!
- \t}\n
- """
- } else {
- methods += """
- \n\tfunc \(fontNameSanitize)(withSize size: CGFloat) -> UIFont {
- \tUIFont(name: FontName.\(fontNameSanitize).rawValue, size: size)!
- \t}\n
- """
- }
- }
-
- return methods
- }
-}
diff --git a/Sources/FontTool/FontToolError.swift b/Sources/FontTool/FontToolError.swift
index 1eb6512..8c68069 100644
--- a/Sources/FontTool/FontToolError.swift
+++ b/Sources/FontTool/FontToolError.swift
@@ -11,17 +11,21 @@ enum FontToolError: Error {
case fcScan(String, Int32, String?)
case inputFolderNotFound(String)
case fileNotExists(String)
+ case writeExtension(String, String)
var localizedDescription: String {
switch self {
case .fcScan(let path, let code, let output):
- return "error:[FontTool] Error while getting fontName (fc-scan --format %{postscriptname} \(path). fc-scan exit with \(code) and output is: \(output ?? "no output")"
+ return "error:[\(FontTool.toolName)] Error while getting fontName (fc-scan --format %{postscriptname} \(path). fc-scan exit with \(code) and output is: \(output ?? "no output")"
case .inputFolderNotFound(let inputFolder):
- return " error:[FontTool] Input folder not found: \(inputFolder)"
+ return " error:[\(FontTool.toolName)] Input folder not found: \(inputFolder)"
case .fileNotExists(let filename):
- return " error:[FontTool] File \(filename) does not exists"
+ return " error:[\(FontTool.toolName)] File \(filename) does not exists"
+
+ case .writeExtension(let filename, let info):
+ return "error:[\(FontTool.toolName)] An error occured while writing extension in \(filename): \(info)"
}
}
}
diff --git a/Sources/FontTool/FontToolHelper.swift b/Sources/FontTool/FontToolHelper.swift
index af758fa..22123e8 100644
--- a/Sources/FontTool/FontToolHelper.swift
+++ b/Sources/FontTool/FontToolHelper.swift
@@ -9,7 +9,32 @@ import Foundation
import ToolCore
class FontToolHelper {
- static func getFontsFilenames(fromInputFolder inputFolder: String) -> [String] {
+
+ static func getFontPostScriptName(for fonts: [String], inputFolder: String) -> [FontName] {
+ let fontsFilenames = Self.getFontsFilenames(fromInputFolder: inputFolder)
+ .filter { fontNameWithPath in
+ let fontName = URL(fileURLWithPath: fontNameWithPath)
+ .deletingPathExtension()
+ .lastPathComponent
+
+ if fonts.contains(fontName) {
+ return true
+ }
+ return false
+ }
+
+ let fontsFilesnamesWithPath = fontsFilenames.map {
+ "\(inputFolder)/\($0)"
+ }
+
+ return fontsFilesnamesWithPath.compactMap {
+ Self.getFontName(atPath: $0)
+ }
+ }
+
+ // MARK: - Private
+
+ private static func getFontsFilenames(fromInputFolder inputFolder: String) -> [String] {
// Get a enumerator for all files
let fileManager = FileManager()
guard fileManager.fileExists(atPath: inputFolder) else {
@@ -32,11 +57,6 @@ class FontToolHelper {
return fontsFileNames
}
- static func getFontsNames(fontsFileNames: [String]) -> [String] {
- // Get font name (font name and font file name can be different)
- fontsFileNames.compactMap { getFontName(atPath: $0) }
- }
-
private static func getFontName(atPath path: String) -> String {
//print("fc-scan --format %{postscriptname} \(path)")
// Get real font name
diff --git a/Sources/FontTool/Generator/FontPlistGenerator.swift b/Sources/FontTool/Generator/FontPlistGenerator.swift
new file mode 100644
index 0000000..e127fef
--- /dev/null
+++ b/Sources/FontTool/Generator/FontPlistGenerator.swift
@@ -0,0 +1,22 @@
+//
+// File.swift
+//
+//
+// Created by Thibaut Schmitt on 29/08/2022.
+//
+
+import Foundation
+
+class FontPlistGenerator {
+ static func generatePlistUIAppsFontContent(for fonts: [FontName]) -> String {
+ var plistData = "UIAppFonts\n\t\n"
+ fonts
+ .compactMap { $0 }
+ .forEach {
+ plistData += "\t\t\($0)\n"
+ }
+ plistData += "\t\n*/"
+
+ return plistData
+ }
+}
diff --git a/Sources/FontTool/Generator/FontToolContentGenerator.swift b/Sources/FontTool/Generator/FontToolContentGenerator.swift
new file mode 100644
index 0000000..018071a
--- /dev/null
+++ b/Sources/FontTool/Generator/FontToolContentGenerator.swift
@@ -0,0 +1,83 @@
+//
+// FontToolContentGenerator.swift
+//
+//
+// Created by Thibaut Schmitt on 13/12/2021.
+//
+
+import Foundation
+import ToolCore
+
+class FontExtensionGenerator {
+
+ static func writeExtensionFile(fontsNames: [String], staticVar: Bool, extensionName: String, extensionFilePath: String) {
+ // Check file if not exists
+ let fileManager = FileManager()
+ if fileManager.fileExists(atPath: extensionFilePath) == false {
+ Shell.shell("touch", "\(extensionFilePath)")
+ }
+
+ // Create extension content
+ let extensionContent = [
+ Self.getHeader(extensionClassname: extensionName),
+ Self.getFontNameEnum(fontsNames: fontsNames),
+ Self.getFontMethods(fontsNames: fontsNames, staticVar: staticVar),
+ Self.getFooter()
+ ]
+ .joined(separator: "\n")
+
+ // Write content
+ let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
+ do {
+ try extensionContent.write(to: extensionFilePathURL, atomically: true, encoding: .utf8)
+ } catch (let error) {
+ let error = FontToolError.writeExtension(extensionFilePath, error.localizedDescription)
+ print(error.localizedDescription)
+ FontTool.exit(withError: error)
+ }
+ }
+
+ private static func getHeader(extensionClassname: String) -> String {
+ """
+ // Generated by ResgenSwift.\(FontTool.toolName) \(ResgenSwiftVersion)
+
+ import UIKit
+
+ extension \(extensionClassname) {\n
+ """
+ }
+
+ private static func getFontNameEnum(fontsNames: [String]) -> String {
+ var enumDefinition = "\tenum FontName: String {\n"
+
+ fontsNames.forEach {
+ enumDefinition += "\t\tcase \($0.removeCharacters(from: "[]+-_")) = \"\($0)\"\n"
+ }
+ enumDefinition += "\t}\n"
+
+ return enumDefinition
+ }
+
+ private static func getFontMethods(fontsNames: [FontName], staticVar: Bool) -> String {
+ let pragma = "\t// MARK: - Getter"
+
+ var propertiesOrMethods: [String] = fontsNames
+ .unique()
+ .map {
+ if staticVar {
+ return $0.staticProperty
+ } else {
+ return $0.method
+ }
+ }
+
+ propertiesOrMethods.insert(pragma, at: 0)
+ return propertiesOrMethods.joined(separator: "\n\n")
+ }
+
+ private static func getFooter() -> String {
+ """
+ }
+ """
+ }
+}
diff --git a/Sources/FontTool/Model/FontName.swift b/Sources/FontTool/Model/FontName.swift
new file mode 100644
index 0000000..e904ee1
--- /dev/null
+++ b/Sources/FontTool/Model/FontName.swift
@@ -0,0 +1,32 @@
+//
+// File.swift
+//
+//
+// Created by Thibaut Schmitt on 29/08/2022.
+//
+
+import Foundation
+
+typealias FontName = String
+
+extension FontName {
+ var fontNameSanitize: String {
+ self.removeCharacters(from: "[]+-_")
+ }
+
+ var method: String {
+ """
+ func \(fontNameSanitize)(withSize size: CGFloat) -> UIFont {
+ UIFont(name: FontName.\(fontNameSanitize).rawValue, size: size)!
+ }
+ """
+ }
+
+ var staticProperty: String {
+ """
+ static let \(fontNameSanitize): ((_ size: CGFloat) -> UIFont) = { size in
+ UIFont(name: FontName.\(fontNameSanitize).rawValue, size: size)!
+ }
+ """
+ }
+}
diff --git a/Sources/FontTool/Parser/FontFileParser.swift b/Sources/FontTool/Parser/FontFileParser.swift
new file mode 100644
index 0000000..bbf1a89
--- /dev/null
+++ b/Sources/FontTool/Parser/FontFileParser.swift
@@ -0,0 +1,16 @@
+//
+// File.swift
+//
+//
+// Created by Thibaut Schmitt on 29/08/2022.
+//
+
+import Foundation
+
+class FontFileParser {
+ static func parse(_ inputFile: String) -> [String] {
+ let inputFileContent = try! String(contentsOfFile: inputFile,
+ encoding: .utf8)
+ return inputFileContent.components(separatedBy: CharacterSet.newlines)
+ }
+}
diff --git a/Sources/FontTool/main.swift b/Sources/FontTool/main.swift
index 2949b5a..7992a69 100644
--- a/Sources/FontTool/main.swift
+++ b/Sources/FontTool/main.swift
@@ -10,19 +10,72 @@ import ToolCore
import ArgumentParser
struct FontTool: ParsableCommand {
- static var configuration = CommandConfiguration(abstract: "Generate fonts plist info and extension to access fonts easily.")
+
+ // MARK: - CommandConfiguration
+
+ static var configuration = CommandConfiguration(
+ abstract: "A utility to generate an helpful etension to access your custom font from code and also Info.plist UIAppsFont content.",
+ version: "0.1.0"
+ )
+
+ // MARK: - Static
+
+ static let toolName = "FontTool"
static let defaultExtensionName = "UIFont"
+ // MARK: - Properties
+
+ var extensionFileName: String {
+ if options.extensionSuffix.isEmpty == false {
+ return "\(options.extensionName)+\(options.extensionSuffix).swift"
+ }
+ return "\(options.extensionName).swift"
+ }
+ var extensionFilePath: String { "\(options.extensionOutputPath)/\(extensionFileName)" }
+ var generateStaticVariable: Bool {
+ options.extensionName == Self.defaultExtensionName
+ }
+
+ // MARK: - Command Options
+
@OptionGroup var options: FontOptions
- var extensionFileName: String { "\(options.extensionName)+\(options.extensionSuffix).swift" }
- var extensionFilePath: String { "\(options.extensionOutputPath)/\(extensionFileName)" }
+ // MARK: - Run
public func run() throws {
- print("[FontTool] Starting fonts generation")
+ print("[\(Self.toolName)] Starting fonts generation")
// Check requirements
+ guard checkRequirements() else { return }
+
+ print("[\(Self.toolName)] Will generate fonts")
+
+ // Get fonts to generate
+ let fontsToGenerate = FontFileParser.parse(options.inputFile)
+
+ // Get real font names
+ let inputFolder = URL(fileURLWithPath: options.inputFile).deletingLastPathComponent().relativePath
+ let fontsNames = FontToolHelper.getFontPostScriptName(for: fontsToGenerate,
+ inputFolder: inputFolder)
+
+ // Generate extension
+ FontExtensionGenerator.writeExtensionFile(fontsNames: fontsNames,
+ staticVar: generateStaticVariable,
+ extensionName: options.extensionName,
+ extensionFilePath: extensionFilePath)
+
+ print("Info.plist information:")
+ print("\(FontPlistGenerator.generatePlistUIAppsFontContent(for: fontsNames))")
+
+ print("[\(Self.toolName)] Fonts generated")
+ }
+
+ // MARK: - Requirements
+
+ private func checkRequirements() -> Bool {
let fileManager = FileManager()
+
+ // Check input file exists
guard fileManager.fileExists(atPath: options.inputFile) else {
let error = FontToolError.fileNotExists(options.inputFile)
print(error.localizedDescription)
@@ -31,86 +84,11 @@ struct FontTool: ParsableCommand {
// Check if needed to regenerate
guard GeneratorChecker.shouldGenerate(force: options.forceGeneration, inputFilePath: options.inputFile, extensionFilePath: extensionFilePath) else {
- print("[FontTool] Fonts are already up to date :) ")
- return
- }
- print("[FontTool] Will generate fonts")
-
- // Get fonts to generate
- let fontsToGenerate = getFontsToGenerate()
-
- let inputFolder = URL(fileURLWithPath: options.inputFile).deletingLastPathComponent().relativePath
- let fontsFilenames = FontToolHelper
- .getFontsFilenames(fromInputFolder: inputFolder)
- .filter { fontNameWithPath in
- let fontName = URL(fileURLWithPath: fontNameWithPath)
- .deletingPathExtension()
- .lastPathComponent
-
- if fontsToGenerate.contains(fontName) {
- return true
- }
- return false
- }
-
- let fontsFilesnamesWithPath = fontsFilenames.map { "\(inputFolder)/\($0)" }
- let fontsNames = FontToolHelper.getFontsNames(fontsFileNames: fontsFilesnamesWithPath)
-
- // Adding fontsFilenames to header (ex: path/to/font.ttf) to make check of regeneration faster
- let extensionHeader = FontToolContentGenerator.getExtensionHeader(fontsNames: fontsFilenames)
-
- let extensionDefinitionOpening = "extension \(options.extensionName) {\n"
- let extensionFontsNamesEnum = FontToolContentGenerator.getFontNameEnum(fontsNames: fontsNames)
- let extensionFontsMethods = FontToolContentGenerator.getFontMethods(fontsNames: fontsNames, isUIFontExtension: isUIFontExtension())
- let extensionDefinitionClosing = "}"
-
- generateExtensionFile(extensionHeader,
- extensionDefinitionOpening,
- extensionFontsNamesEnum,
- extensionFontsMethods,
- extensionDefinitionClosing)
-
- print("Info.plist information:")
- print("\(generatePlistUIAppFonts(fontsNames: fontsNames))")
-
- print("[FontTool] Fonts generated")
- }
-
- private func generateExtensionFile(_ args: String...) {
- // Create file if not exists
- let fileManager = FileManager()
- if fileManager.fileExists(atPath: extensionFilePath) == false {
- Shell.shell("touch", "\(extensionFilePath)")
+ print("[\(Self.toolName)] Fonts are already up to date :) ")
+ return false
}
- // Create extension content
- let extensionContent = args.joined(separator: "\n")
-
- // Write content
- let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
- try! extensionContent.write(to: extensionFilePathURL, atomically: true, encoding: .utf8)
- }
-
- private func generatePlistUIAppFonts(fontsNames: [String]) -> String {
- var plistData = "UIAppFonts\n\t\n"
- fontsNames
- .compactMap { $0 }
- .forEach {
- plistData += "\t\t\($0)\n"
- }
- plistData += "\t\n*/"
-
- return plistData
- }
- // MARK: - Helpers
-
- private func getFontsToGenerate() -> [String] {
- let inputFileContent = try! String(contentsOfFile: options.inputFile, encoding: .utf8)
- return inputFileContent.components(separatedBy: CharacterSet.newlines)
- }
-
- private func isUIFontExtension() -> Bool {
- options.extensionName == Self.defaultExtensionName
+ return true
}
}
diff --git a/Sources/Imagium/FileManagerExtensions.swift b/Sources/Imagium/Extensions/FileManagerExtensions.swift
similarity index 100%
rename from Sources/Imagium/FileManagerExtensions.swift
rename to Sources/Imagium/Extensions/FileManagerExtensions.swift
diff --git a/Sources/Imagium/ImageExtensionGenerator.swift b/Sources/Imagium/Generator/ImageExtensionGenerator.swift
similarity index 94%
rename from Sources/Imagium/ImageExtensionGenerator.swift
rename to Sources/Imagium/Generator/ImageExtensionGenerator.swift
index f7fde30..9dcf1e2 100644
--- a/Sources/Imagium/ImageExtensionGenerator.swift
+++ b/Sources/Imagium/Generator/ImageExtensionGenerator.swift
@@ -12,7 +12,7 @@ class ImageExtensionGenerator {
// MARK: - Extension files
- static func writeStringsFiles(images: [ImageToGen], staticVar: Bool, inputFilename: String, extensionName: String, extensionFilePath: String) {
+ static func writeStringsFiles(images: [ParsedImage], staticVar: Bool, inputFilename: String, extensionName: String, extensionFilePath: String) {
// Get header/footer
let extensionHeader = Self.getHeader(inputFilename: inputFilename, extensionClassname: extensionName)
let extensionFooter = Self.getFooter()
diff --git a/Sources/Imagium/XcassetsGenerator.swift b/Sources/Imagium/Generator/XcassetsGenerator.swift
similarity index 83%
rename from Sources/Imagium/XcassetsGenerator.swift
rename to Sources/Imagium/Generator/XcassetsGenerator.swift
index 39ae382..17cee8d 100644
--- a/Sources/Imagium/XcassetsGenerator.swift
+++ b/Sources/Imagium/Generator/XcassetsGenerator.swift
@@ -22,7 +22,7 @@ class XcassetsGenerator {
// MARK: - Assets generation
- func generateXcassets(inputPath: String, imagesToGenerate: [ImageToGen], xcassetsPath: String) {
+ func generateXcassets(inputPath: String, imagesToGenerate: [ParsedImage], xcassetsPath: String) {
let fileManager = FileManager()
let svgConverter = Imagium.getSvgConverterPath()
let allSubFiles = fileManager.getAllRegularFileIn(directory: inputPath)
@@ -30,30 +30,30 @@ class XcassetsGenerator {
var generatedAssetsPaths = [String]()
// Generate new assets
- imagesToGenerate.forEach { imageToGen in
+ imagesToGenerate.forEach { parsedImage in
// Get image path
let imageData: (path: String, ext: String) = {
for subfile in allSubFiles {
- if subfile.hasSuffix("/" + imageToGen.name + ".svg") {
+ if subfile.hasSuffix("/" + parsedImage.name + ".svg") {
return (subfile, "svg")
}
- if subfile.hasSuffix("/" + imageToGen.name + ".png") {
+ if subfile.hasSuffix("/" + parsedImage.name + ".png") {
return (subfile, "png")
}
- if subfile.hasSuffix("/" + imageToGen.name + ".jpg") {
+ if subfile.hasSuffix("/" + parsedImage.name + ".jpg") {
return (subfile, "jpg")
}
- if subfile.hasSuffix("/" + imageToGen.name + ".jepg") {
+ if subfile.hasSuffix("/" + parsedImage.name + ".jepg") {
return (subfile, "jepg")
}
}
- let error = ImagiumError.unknownImageExtension(imageToGen.name)
+ let error = ImagiumError.unknownImageExtension(parsedImage.name)
print(error.localizedDescription)
Imagium.exit(withError: error)
}()
// Create imageset folder
- let imagesetName = "\(imageToGen.name).imageset"
+ let imagesetName = "\(parsedImage.name).imageset"
let imagesetPath = "\(xcassetsPath)/\(imagesetName)"
Shell.shell("mkdir", "-p", imagesetPath)
@@ -61,18 +61,18 @@ class XcassetsGenerator {
generatedAssetsPaths.append(imagesetName)
// Generate output images path
- let output1x = "\(imagesetPath)/\(imageToGen.name).\(XcassetsGenerator.outputImageExtension)"
- let output2x = "\(imagesetPath)/\(imageToGen.name)@2x.\(XcassetsGenerator.outputImageExtension)"
- let output3x = "\(imagesetPath)/\(imageToGen.name)@3x.\(XcassetsGenerator.outputImageExtension)"
+ let output1x = "\(imagesetPath)/\(parsedImage.name).\(XcassetsGenerator.outputImageExtension)"
+ let output2x = "\(imagesetPath)/\(parsedImage.name)@2x.\(XcassetsGenerator.outputImageExtension)"
+ let output3x = "\(imagesetPath)/\(parsedImage.name)@3x.\(XcassetsGenerator.outputImageExtension)"
// Check if we need to convert image
- if self.shouldBypassGeneration(for: imageToGen, xcassetImagePath: output1x) {
- print("\(imageToGen.name) -> Not regenerating")
+ if self.shouldBypassGeneration(for: parsedImage, xcassetImagePath: output1x) {
+ print("\(parsedImage.name) -> Not regenerating")
return
}
// Convert image
- let convertArguments = imageToGen.convertArguments
+ let convertArguments = parsedImage.convertArguments
if imageData.ext == "svg" {
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -h 300 -o path/to/output.png
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -o path/to/output.png
@@ -102,7 +102,7 @@ class XcassetsGenerator {
}
// Write Content.json
- let imagesetContentJson = imageToGen.contentJson
+ let imagesetContentJson = parsedImage.contentJson
let contentJsonFilePath = "\(imagesetPath)/Contents.json"
if fileManager.fileExists(atPath: contentJsonFilePath) == false {
Shell.shell("touch", "\(contentJsonFilePath)")
@@ -111,7 +111,7 @@ class XcassetsGenerator {
let contentJsonFilePathURL = URL(fileURLWithPath: contentJsonFilePath)
try! imagesetContentJson.write(to: contentJsonFilePathURL, atomically: true, encoding: .utf8)
- print("\(imageToGen.name) -> Generated")
+ print("\(parsedImage.name) -> Generated")
}
// Success info
@@ -147,7 +147,7 @@ class XcassetsGenerator {
// MARK: - Helpers: bypass generation
- private func shouldBypassGeneration(for image: ImageToGen, xcassetImagePath: String) -> Bool {
+ private func shouldBypassGeneration(for image: ParsedImage, xcassetImagePath: String) -> Bool {
guard forceGeneration == false else {
return false
}
diff --git a/Sources/Imagium/ConvertArgument.swift b/Sources/Imagium/Model/ConvertArgument.swift
similarity index 100%
rename from Sources/Imagium/ConvertArgument.swift
rename to Sources/Imagium/Model/ConvertArgument.swift
diff --git a/Sources/Imagium/ImageToGen.swift b/Sources/Imagium/Model/ParsedImage.swift
similarity index 98%
rename from Sources/Imagium/ImageToGen.swift
rename to Sources/Imagium/Model/ParsedImage.swift
index 760c821..800facb 100644
--- a/Sources/Imagium/ImageToGen.swift
+++ b/Sources/Imagium/Model/ParsedImage.swift
@@ -1,5 +1,5 @@
//
-// File.swift
+// ParsedImage.swift
//
//
// Created by Thibaut Schmitt on 24/01/2022.
@@ -7,7 +7,7 @@
import Foundation
-struct ImageToGen {
+struct ParsedImage {
let name: String
let tags: String
let width: Int
diff --git a/Sources/Imagium/Model/PlatormTag.swift b/Sources/Imagium/Model/PlatormTag.swift
new file mode 100644
index 0000000..b7fca9c
--- /dev/null
+++ b/Sources/Imagium/Model/PlatormTag.swift
@@ -0,0 +1,13 @@
+//
+// PlatormTag.swift
+//
+//
+// Created by Thibaut Schmitt on 29/08/2022.
+//
+
+import Foundation
+
+enum PlatormTag: String {
+ case droid = "d"
+ case ios = "i"
+}
diff --git a/Sources/Imagium/ImageFileParser.swift b/Sources/Imagium/Parser/ImageFileParser.swift
similarity index 86%
rename from Sources/Imagium/ImageFileParser.swift
rename to Sources/Imagium/Parser/ImageFileParser.swift
index 7355963..1b173fe 100644
--- a/Sources/Imagium/ImageFileParser.swift
+++ b/Sources/Imagium/Parser/ImageFileParser.swift
@@ -9,11 +9,11 @@ import Foundation
class ImageFileParser {
- static func parse(_ inputFile: String, platform: PlatormTag) -> [ImageToGen] {
+ static func parse(_ inputFile: String, platform: PlatormTag) -> [ParsedImage] {
let inputFileContent = try! String(contentsOfFile: inputFile, encoding: .utf8)
let stringsByLines = inputFileContent.components(separatedBy: .newlines)
- var imagesToGenerate = [ImageToGen]()
+ var imagesToGenerate = [ParsedImage]()
// Parse file
stringsByLines.forEach {
@@ -36,7 +36,7 @@ class ImageFileParser {
return Int(splittedLine[3])!
}()
- let image = ImageToGen(name: String(splittedLine[1]), tags: String(splittedLine[0]), width: width, height: height)
+ let image = ParsedImage(name: String(splittedLine[1]), tags: String(splittedLine[0]), width: width, height: height)
imagesToGenerate.append(image)
}
diff --git a/Sources/Imagium/main.swift b/Sources/Imagium/main.swift
index fb2c529..5102ff2 100644
--- a/Sources/Imagium/main.swift
+++ b/Sources/Imagium/main.swift
@@ -9,21 +9,22 @@ import Foundation
import ArgumentParser
import ToolCore
-enum PlatormTag: String {
- case droid = "d"
- case ios = "i"
-}
-
struct Imagium: ParsableCommand {
+ // MARK: - CommandConfiguration
+
static var configuration = CommandConfiguration(
- abstract: "A utility for generate images.",
+ abstract: "A utility for generate images and an extension to access them easily.",
version: "0.1.0"
)
+ // MARK: - Static
+
static let toolName = "Imagium"
static let defaultExtensionName = "UIImage"
+ // MARK: - Properties
+
var extensionFileName: String { "\(options.extensionName)+\(options.extensionSuffix).swift" }
var extensionFilePath: String { "\(options.extensionOutputPath)/\(extensionFileName)" }
var inputFilenameWithoutExt: String {
@@ -32,8 +33,12 @@ struct Imagium: ParsableCommand {
.lastPathComponent
}
+ // MARK: - Command Options
+
@OptionGroup var options: ImagiumOptions
+ // MARK: - Run
+
mutating func run() {
print("[\(Self.toolName)] Starting images generation")
diff --git a/Sources/Strings/Generator/StringsFileGenerator.swift b/Sources/Strings/Generator/StringsFileGenerator.swift
index bc1579d..83971fc 100644
--- a/Sources/Strings/Generator/StringsFileGenerator.swift
+++ b/Sources/Strings/Generator/StringsFileGenerator.swift
@@ -137,7 +137,7 @@ class StringsFileGenerator {
private static func getHeader(stringsFilename: String, extensionClassname: String) -> String {
"""
- // Generated by ResgenSwift.Strings.Stringium \(ResgenSwiftVersion)
+ // Generated by ResgenSwift.Strings.\(Stringium.toolName) \(ResgenSwiftVersion)
import UIKit
diff --git a/Sources/Strings/Stringium/Stringium.swift b/Sources/Strings/Stringium/Stringium.swift
index cbc7bf8..e11eaf1 100644
--- a/Sources/Strings/Stringium/Stringium.swift
+++ b/Sources/Strings/Stringium/Stringium.swift
@@ -10,37 +10,49 @@ import ToolCore
import ArgumentParser
struct Stringium: ParsableCommand {
- static var configuration = CommandConfiguration(abstract: "Generate strings with custom scripts.")
+
+ // MARK: - Command Configuration
+
+ static var configuration = CommandConfiguration(
+ abstract: "Generate strings with custom scripts.",
+ version: "0.1.0"
+ )
+
+ // MARK: - Static
static let toolName = "Stringium"
static let defaultExtensionName = "String"
static let noTranslationTag: String = "notranslation"
- var extensionFileName: String { "\(options.extensionName)+\(options.extensionSuffix).swift" }
+ // MARK: - Properties
+
+ var extensionFileName: String {
+ if options.extensionSuffix.isEmpty == false {
+ return "\(options.extensionName)+\(options.extensionSuffix).swift"
+ }
+ return "\(options.extensionName).swift"
+ }
+
var extensionFilePath: String { "\(options.extensionOutputPath)/\(extensionFileName)" }
- var langs: [String] {
- options.langsRaw
- .split(separator: " ")
- .map { String($0) }
- }
var inputFilenameWithoutExt: String {
URL(fileURLWithPath: options.inputFile)
.deletingPathExtension()
.lastPathComponent
}
- var stringsFileOutputPath: String {
- var outputPath = options.outputPathRaw
- if outputPath.last == "/" {
- outputPath = String(outputPath.dropLast())
- }
- return outputPath
+
+ var generateStaticVariable: Bool {
+ options.extensionName == Self.defaultExtensionName
}
+ // MARK: - Command options
+
// The `@OptionGroup` attribute includes the flags, options, and
// arguments defined by another `ParsableArguments` type.
@OptionGroup var options: StringiumOptions
+ // MARK: - Run
+
mutating func run() {
print("[\(Self.toolName)] Starting strings generation")
@@ -54,17 +66,17 @@ struct Stringium: ParsableCommand {
// Generate strings files
StringsFileGenerator.writeStringsFiles(sections: sections,
- langs: langs,
+ langs: options.langs,
defaultLang: options.defaultLang,
- tags: ["ios", "iosonly", Self.noTranslationTag],
- outputPath: stringsFileOutputPath,
+ tags: options.tags,
+ outputPath: options.stringsFileOutputPath,
inputFilenameWithoutExt: inputFilenameWithoutExt)
// Generate extension
StringsFileGenerator.writeExtensionFiles(sections: sections,
defaultLang: options.defaultLang,
- tags: ["ios", "iosonly", Self.noTranslationTag],
- staticVar: options.extensionName == Self.defaultExtensionName,
+ tags: options.tags,
+ staticVar: generateStaticVariable,
inputFilename: inputFilenameWithoutExt,
extensionName: options.extensionName,
extensionFilePath: extensionFilePath)
@@ -85,13 +97,13 @@ struct Stringium: ParsableCommand {
}
// Langs
- guard langs.isEmpty == false else {
+ guard options.langs.isEmpty == false else {
let error = StringiumError.langsListEmpty
print(error.localizedDescription)
Stringium.exit(withError: error)
}
- guard langs.contains(options.defaultLang) else {
+ guard options.langs.contains(options.defaultLang) else {
let error = StringiumError.defaultLangsNotInLangs
print(error.localizedDescription)
Stringium.exit(withError: error)
diff --git a/Sources/Strings/Stringium/StringiumOptions.swift b/Sources/Strings/Stringium/StringiumOptions.swift
index b5b0130..61d715a 100644
--- a/Sources/Strings/Stringium/StringiumOptions.swift
+++ b/Sources/Strings/Stringium/StringiumOptions.swift
@@ -16,20 +16,45 @@ struct StringiumOptions: ParsableArguments {
var inputFile: String
@Option(name: .customLong("output-path"), help: "Path where to strings file.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
- var outputPathRaw: String
+ fileprivate var outputPathRaw: String
@Option(name: .customLong("langs"), help: "Langs to generate.")
- var langsRaw: String
+ fileprivate var langsRaw: String
@Option(help: "Default langs.")
var defaultLang: String
+ @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: "Extension name. If not specified, it will generate an String extension. Using default extension name will generate static property.")
var extensionName: String = Stringium.defaultExtensionName
- @Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+String{extensionSuffix}.swift")
+ @Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+{extensionSuffix}.swift")
var extensionSuffix: String = ""
}
+
+extension StringiumOptions {
+ var stringsFileOutputPath: String {
+ var outputPath = outputPathRaw
+ if outputPath.last == "/" {
+ outputPath = String(outputPath.dropLast())
+ }
+ return outputPath
+ }
+
+ var langs: [String] {
+ langsRaw
+ .split(separator: " ")
+ .map { String($0) }
+ }
+
+ var tags: [String] {
+ tagsRaw
+ .split(separator: " ")
+ .map { String($0) }
+ }
+}
diff --git a/Sources/Strings/Tag/Tags.swift b/Sources/Strings/Tag/Tags.swift
index 18278cf..eacc793 100644
--- a/Sources/Strings/Tag/Tags.swift
+++ b/Sources/Strings/Tag/Tags.swift
@@ -10,19 +10,42 @@ import ToolCore
import ArgumentParser
struct Tags: ParsableCommand {
- static var configuration = CommandConfiguration(abstract: "Generate tags extension file.")
+
+ // MARK: - Command Configuration
+
+ static var configuration = CommandConfiguration(
+ abstract: "Generate tags extension file.",
+ version: "0.1.0"
+ )
+
+
+ // MARK: - Static
static let toolName = "Tags"
static let defaultExtensionName = "Tags"
static let noTranslationTag: String = "notranslation"
- var extensionFileName: String { "\(options.extensionName)+\(options.extensionSuffix).swift" }
+ // MARK: - Properties
+
+ var extensionFileName: String {
+ if options.extensionSuffix.isEmpty == false {
+ return "\(options.extensionName)+\(options.extensionSuffix).swift"
+ }
+ return "\(options.extensionName).swift"
+ }
var extensionFilePath: String { "\(options.extensionOutputPath)/\(extensionFileName)" }
+ var generateStaticVariable: Bool {
+ options.extensionName == Self.defaultExtensionName
+ }
+
+ // MARK: - Command Options
// The `@OptionGroup` attribute includes the flags, options, and
// arguments defined by another `ParsableArguments` type.
@OptionGroup var options: TagsOptions
+ // MARK: - Run
+
mutating func run() {
print("[\(Self.toolName)] Starting tagss generation")
@@ -38,7 +61,7 @@ struct Tags: ParsableCommand {
TagsGenerator.writeExtensionFiles(sections: sections,
lang: options.lang,
tags: ["ios", "iosonly", Self.noTranslationTag],
- staticVar: options.extensionName == Self.defaultExtensionName,
+ staticVar: generateStaticVariable,
extensionName: options.extensionName,
extensionFilePath: extensionFilePath)
diff --git a/Sources/Strings/Twine/Twine.swift b/Sources/Strings/Twine/Twine.swift
index 53626fd..7653d9c 100644
--- a/Sources/Strings/Twine/Twine.swift
+++ b/Sources/Strings/Twine/Twine.swift
@@ -10,22 +10,35 @@ import ToolCore
import ArgumentParser
struct Twine: ParsableCommand {
- static var configuration = CommandConfiguration(abstract: "Generate strings with twine.")
+
+ // MARK: - Command Configuration
+
+ static var configuration = CommandConfiguration(
+ abstract: "Generate strings with twine.",
+ version: "0.1.0"
+ )
+
+ // MARK: - Static
static let toolName = "Twine"
static let defaultExtensionName = "String"
static let twineExecutable = "\(FileManager.default.homeDirectoryForCurrentUser.relativePath)/scripts/twine/twine"
- var langs: [String] { options.langsRaw.split(separator: " ").map { String($0) } }
+ // MARK: - Properties
+
var inputFilenameWithoutExt: String { URL(fileURLWithPath: options.inputFile)
.deletingPathExtension()
.lastPathComponent
}
+ // MARK: - Command Options
+
// The `@OptionGroup` attribute includes the flags, options, and
// arguments defined by another `ParsableArguments` type.
@OptionGroup var options: TwineOptions
+ // MARK: - Run
+
mutating func run() {
print("[\(Self.toolName)] Starting strings generation")
@@ -35,7 +48,7 @@ struct Twine: ParsableCommand {
print("[\(Self.toolName)] Will generate strings")
// Generate strings files (lproj files)
- for lang in langs {
+ for lang in options.langs {
Shell.shell(Self.twineExecutable,
"generate-localization-file", options.inputFile,
"--lang", "\(lang)",
@@ -68,13 +81,13 @@ struct Twine: ParsableCommand {
}
// Langs
- guard langs.isEmpty == false else {
+ guard options.langs.isEmpty == false else {
let error = TwineError.langsListEmpty
print(error.localizedDescription)
Twine.exit(withError: error)
}
- guard langs.contains(options.defaultLang) else {
+ guard options.langs.contains(options.defaultLang) else {
let error = TwineError.defaultLangsNotInLangs
print(error.localizedDescription)
Twine.exit(withError: error)
diff --git a/Sources/Strings/Twine/TwineOptions.swift b/Sources/Strings/Twine/TwineOptions.swift
index 4d1d559..1c020ec 100644
--- a/Sources/Strings/Twine/TwineOptions.swift
+++ b/Sources/Strings/Twine/TwineOptions.swift
@@ -19,7 +19,7 @@ struct TwineOptions: ParsableArguments {
var outputPath: String
@Option(name: .customLong("langs"), help: "Langs to generate.")
- var langsRaw: String
+ fileprivate var langsRaw: String
@Option(help: "Default langs.")
var defaultLang: String
@@ -27,3 +27,11 @@ struct TwineOptions: ParsableArguments {
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
var extensionOutputPath: String
}
+
+extension TwineOptions {
+ var langs: [String] {
+ langsRaw
+ .split(separator: " ")
+ .map { String($0) }
+ }
+}