//
// FontTool.swift
//
//
// Created by Thibaut Schmitt on 13/12/2021.
//
import Foundation
import CLIToolCore
import ArgumentParser
struct FontTool: ParsableCommand {
static var configuration = CommandConfiguration(abstract: "Generate fonts plist info and extension to access fonts easily.")
static let defaultExtensionName = "UIFont"
@OptionGroup var options: FontOptions
var extensionFileName: String { "\(options.extensionName)+Font\(options.extensionSuffix).swift" }
var extensionFilePath: String { "\(options.extensionOutputPath)/\(extensionFileName)" }
public func run() throws {
print("[FontTool] Starting fonts generation")
// Check requirements
let fileManager = FileManager()
guard fileManager.fileExists(atPath: options.inputFile) else {
let error = FontToolError.fileNotExists(options.inputFile)
print(error.localizedDescription)
FontTool.exit(withError: error)
}
// 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)")
}
// 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
}
}
FontTool.main()