Bugs fixes, Lint fixes, Refactoring
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
This commit is contained in:
@ -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
|
||||
}
|
||||
}
|
@ -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)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
22
Sources/FontTool/Generator/FontPlistGenerator.swift
Normal file
22
Sources/FontTool/Generator/FontPlistGenerator.swift
Normal file
@ -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 = "<key>UIAppFonts</key>\n\t<array>\n"
|
||||
fonts
|
||||
.compactMap { $0 }
|
||||
.forEach {
|
||||
plistData += "\t\t<string>\($0)</string>\n"
|
||||
}
|
||||
plistData += "\t</array>\n*/"
|
||||
|
||||
return plistData
|
||||
}
|
||||
}
|
83
Sources/FontTool/Generator/FontToolContentGenerator.swift
Normal file
83
Sources/FontTool/Generator/FontToolContentGenerator.swift
Normal file
@ -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 {
|
||||
"""
|
||||
}
|
||||
"""
|
||||
}
|
||||
}
|
32
Sources/FontTool/Model/FontName.swift
Normal file
32
Sources/FontTool/Model/FontName.swift
Normal file
@ -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)!
|
||||
}
|
||||
"""
|
||||
}
|
||||
}
|
16
Sources/FontTool/Parser/FontFileParser.swift
Normal file
16
Sources/FontTool/Parser/FontFileParser.swift
Normal file
@ -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)
|
||||
}
|
||||
}
|
@ -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 = "<key>UIAppFonts</key>\n\t<array>\n"
|
||||
fontsNames
|
||||
.compactMap { $0 }
|
||||
.forEach {
|
||||
plistData += "\t\t<string>\($0)</string>\n"
|
||||
}
|
||||
plistData += "\t</array>\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
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user