Add command to generate Colors
This commit is contained in:
parent
e2150059f7
commit
e8545955f6
78
.swiftpm/xcode/xcshareddata/xcschemes/ColorToolCore.xcscheme
Normal file
78
.swiftpm/xcode/xcshareddata/xcschemes/ColorToolCore.xcscheme
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1310"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ColorToolCore"
|
||||||
|
BuildableName = "ColorToolCore"
|
||||||
|
BlueprintName = "ColorToolCore"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ColorToolCore"
|
||||||
|
BuildableName = "ColorToolCore"
|
||||||
|
BlueprintName = "ColorToolCore"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ColorToolCore"
|
||||||
|
BuildableName = "ColorToolCore"
|
||||||
|
BlueprintName = "ColorToolCore"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
78
.swiftpm/xcode/xcshareddata/xcschemes/FontToolCore.xcscheme
Normal file
78
.swiftpm/xcode/xcshareddata/xcschemes/FontToolCore.xcscheme
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1310"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "FontToolCore"
|
||||||
|
BuildableName = "FontToolCore"
|
||||||
|
BlueprintName = "FontToolCore"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "FontToolCore"
|
||||||
|
BuildableName = "FontToolCore"
|
||||||
|
BlueprintName = "FontToolCore"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "FontToolCore"
|
||||||
|
BuildableName = "FontToolCore"
|
||||||
|
BlueprintName = "FontToolCore"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
@ -0,0 +1,142 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1310"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ColorToolCore"
|
||||||
|
BuildableName = "ColorToolCore"
|
||||||
|
BlueprintName = "ColorToolCore"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "FontToolCore"
|
||||||
|
BuildableName = "FontToolCore"
|
||||||
|
BlueprintName = "FontToolCore"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ResgenSwift"
|
||||||
|
BuildableName = "ResgenSwift"
|
||||||
|
BlueprintName = "ResgenSwift"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "NO"
|
||||||
|
buildForArchiving = "NO"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ResgenSwiftTests"
|
||||||
|
BuildableName = "ResgenSwiftTests"
|
||||||
|
BlueprintName = "ResgenSwiftTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "CLIToolCore"
|
||||||
|
BuildableName = "CLIToolCore"
|
||||||
|
BlueprintName = "CLIToolCore"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ResgenSwiftTests"
|
||||||
|
BuildableName = "ResgenSwiftTests"
|
||||||
|
BlueprintName = "ResgenSwiftTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ColorToolCore"
|
||||||
|
BuildableName = "ColorToolCore"
|
||||||
|
BlueprintName = "ColorToolCore"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ResgenSwift"
|
||||||
|
BuildableName = "ResgenSwift"
|
||||||
|
BlueprintName = "ResgenSwift"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
102
.swiftpm/xcode/xcshareddata/xcschemes/ResgenSwift.xcscheme
Normal file
102
.swiftpm/xcode/xcshareddata/xcschemes/ResgenSwift.xcscheme
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1310"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ResgenSwift"
|
||||||
|
BuildableName = "ResgenSwift"
|
||||||
|
BlueprintName = "ResgenSwift"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "NO"
|
||||||
|
buildForArchiving = "NO"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ResgenSwiftTests"
|
||||||
|
BuildableName = "ResgenSwiftTests"
|
||||||
|
BlueprintName = "ResgenSwiftTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ResgenSwiftTests"
|
||||||
|
BuildableName = "ResgenSwiftTests"
|
||||||
|
BlueprintName = "ResgenSwiftTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ResgenSwift"
|
||||||
|
BuildableName = "ResgenSwift"
|
||||||
|
BlueprintName = "ResgenSwift"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ResgenSwift"
|
||||||
|
BuildableName = "ResgenSwift"
|
||||||
|
BlueprintName = "ResgenSwift"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
@ -14,13 +14,22 @@ let package = Package(
|
|||||||
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||||
.target(
|
.target(
|
||||||
name: "ResgenSwift",
|
name: "ResgenSwift",
|
||||||
dependencies: ["FontToolCore"]),
|
dependencies: ["FontToolCore", "ColorToolCore"]
|
||||||
|
),
|
||||||
.target(
|
.target(
|
||||||
name: "FontToolCore",
|
name: "FontToolCore",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"CLIToolCore",
|
"CLIToolCore",
|
||||||
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||||
]),
|
]
|
||||||
|
),
|
||||||
|
.target(
|
||||||
|
name: "ColorToolCore",
|
||||||
|
dependencies: [
|
||||||
|
"CLIToolCore",
|
||||||
|
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||||
|
]
|
||||||
|
),
|
||||||
// Helper targets
|
// Helper targets
|
||||||
.target(name: "CLIToolCore"),
|
.target(name: "CLIToolCore"),
|
||||||
// Test targets
|
// Test targets
|
||||||
|
21
SampleFiles/Colors/Generated/R2Color+Font.swift
Normal file
21
SampleFiles/Colors/Generated/R2Color+Font.swift
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Generated from ColorToolCore at 2021-12-20 15:27:15 +0000
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension R2Color {
|
||||||
|
|
||||||
|
/// Color red is #FF0000 (light) or #FF0000 (dark)"
|
||||||
|
@objc var red: UIColor {
|
||||||
|
UIColor(named: "red")!
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Color green_alpha_50 is #A000FF00 (light) or #A000FF00 (dark)"
|
||||||
|
@objc var green_alpha_50: UIColor {
|
||||||
|
UIColor(named: "green_alpha_50")!
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Color blue_light_dark is #0000FF (light) or #0000FF (dark)"
|
||||||
|
@objc var blue_light_dark: UIColor {
|
||||||
|
UIColor(named: "blue_light_dark")!
|
||||||
|
}
|
||||||
|
}
|
21
SampleFiles/Colors/Generated/UIColor+Font.swift
Normal file
21
SampleFiles/Colors/Generated/UIColor+Font.swift
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Generated from ColorToolCore at 2021-12-20 15:16:18 +0000
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIColor {
|
||||||
|
|
||||||
|
/// Color red is #FF0000 (light) or #FF0000 (dark)"
|
||||||
|
static var red: UIColor {
|
||||||
|
UIColor(named: "red")!
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Color green_alpha_50 is #A000FF00 (light) or #A000FF00 (dark)"
|
||||||
|
static var green_alpha_50: UIColor {
|
||||||
|
UIColor(named: "green_alpha_50")!
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Color blue_light_dark is #0000FF (light) or #0000AA (dark)"
|
||||||
|
static var blue_light_dark: UIColor {
|
||||||
|
UIColor(named: "blue_light_dark")!
|
||||||
|
}
|
||||||
|
}
|
21
SampleFiles/Colors/Generated/UIColor+FontSampleApp.swift
Normal file
21
SampleFiles/Colors/Generated/UIColor+FontSampleApp.swift
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Generated from ColorToolCore at 2021-12-20 15:17:10 +0000
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIColor {
|
||||||
|
|
||||||
|
/// Color red is #FF0000 (light) or #FF0000 (dark)"
|
||||||
|
static var red: UIColor {
|
||||||
|
UIColor(named: "red")!
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Color green_alpha_50 is #A000FF00 (light) or #A000FF00 (dark)"
|
||||||
|
static var green_alpha_50: UIColor {
|
||||||
|
UIColor(named: "green_alpha_50")!
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Color blue_light_dark is #0000FF (light) or #0000AA (dark)"
|
||||||
|
static var blue_light_dark: UIColor {
|
||||||
|
UIColor(named: "blue_light_dark")!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"colors": [
|
||||||
|
{
|
||||||
|
"color": {
|
||||||
|
"color-space": "srgb",
|
||||||
|
"components": {
|
||||||
|
"alpha": "0xFF",
|
||||||
|
"blue": "0xFF",
|
||||||
|
"green": "0x00",
|
||||||
|
"red": "0x00",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom": "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances": [
|
||||||
|
{
|
||||||
|
"appearance": "luminosity",
|
||||||
|
"value": "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color": {
|
||||||
|
"color-space": "srgb",
|
||||||
|
"components": {
|
||||||
|
"alpha": "0xFF",
|
||||||
|
"blue": "0xFF",
|
||||||
|
"green": "0x00",
|
||||||
|
"red": "0x00",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom": "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info": {
|
||||||
|
"author": "xcode",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"colors": [
|
||||||
|
{
|
||||||
|
"color": {
|
||||||
|
"color-space": "srgb",
|
||||||
|
"components": {
|
||||||
|
"alpha": "0xA0",
|
||||||
|
"blue": "0x00",
|
||||||
|
"green": "0xFF",
|
||||||
|
"red": "0x00",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom": "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances": [
|
||||||
|
{
|
||||||
|
"appearance": "luminosity",
|
||||||
|
"value": "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color": {
|
||||||
|
"color-space": "srgb",
|
||||||
|
"components": {
|
||||||
|
"alpha": "0xA0",
|
||||||
|
"blue": "0x00",
|
||||||
|
"green": "0xFF",
|
||||||
|
"red": "0x00",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom": "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info": {
|
||||||
|
"author": "xcode",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"colors": [
|
||||||
|
{
|
||||||
|
"color": {
|
||||||
|
"color-space": "srgb",
|
||||||
|
"components": {
|
||||||
|
"alpha": "0xFF",
|
||||||
|
"blue": "0x00",
|
||||||
|
"green": "0x00",
|
||||||
|
"red": "0xFF",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom": "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances": [
|
||||||
|
{
|
||||||
|
"appearance": "luminosity",
|
||||||
|
"value": "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color": {
|
||||||
|
"color-space": "srgb",
|
||||||
|
"components": {
|
||||||
|
"alpha": "0xFF",
|
||||||
|
"blue": "0x00",
|
||||||
|
"green": "0x00",
|
||||||
|
"red": "0xFF",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom": "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info": {
|
||||||
|
"author": "xcode",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
}
|
9
SampleFiles/Colors/sampleColors1.txt
Normal file
9
SampleFiles/Colors/sampleColors1.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Available format:
|
||||||
|
# colorName=#RGB/#ARGB
|
||||||
|
# colorName #RGB/#ARGB
|
||||||
|
# colorName #RGB/#ARGB #RGB/#ARGB
|
||||||
|
|
||||||
|
# Comment line and empty line will be ingored
|
||||||
|
red = #FF0000
|
||||||
|
green_alpha_50 = #A000FF00
|
||||||
|
blue_light_dark = #0000FF #0000AA
|
@ -29,3 +29,35 @@ public class Shell {
|
|||||||
return (terminationStatus: task.terminationStatus, output: output)
|
return (terminationStatus: task.terminationStatus, output: output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class GeneratorChecker {
|
||||||
|
|
||||||
|
/// Return `true` if inputFile is newer than extensionFile, otherwise `false`
|
||||||
|
public static func shouldGenerate(force: Bool, inputFilePath: String, extensionFilePath: String) -> Bool {
|
||||||
|
guard force == false else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// If inputFile is newer that generated extension -> Regenerate
|
||||||
|
let extensionFileURL = URL(fileURLWithPath: extensionFilePath)
|
||||||
|
let inputFileURL = URL(fileURLWithPath: inputFilePath)
|
||||||
|
|
||||||
|
let extensionRessourceValues = try? extensionFileURL.resourceValues(forKeys: [URLResourceKey.contentModificationDateKey])
|
||||||
|
let inputFileRessourceValues = try? inputFileURL.resourceValues(forKeys: [URLResourceKey.contentModificationDateKey])
|
||||||
|
|
||||||
|
if let extensionModificationDate = extensionRessourceValues?.contentModificationDate,
|
||||||
|
let inputFileModificationDate = inputFileRessourceValues?.contentModificationDate {
|
||||||
|
if inputFileModificationDate >= extensionModificationDate {
|
||||||
|
print("Input file is newer that generated extension.")
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModificationDate not available for both file
|
||||||
|
print("⚠️ Could not compare file modication date. ⚠️")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
64
Sources/CLIToolCore/Extensions.swift
Normal file
64
Sources/CLIToolCore/Extensions.swift
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
//
|
||||||
|
// Extensions.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 13/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
// MARK: - String
|
||||||
|
|
||||||
|
public extension String {
|
||||||
|
func removeCharacters(from forbiddenChars: CharacterSet) -> String {
|
||||||
|
let passed = self.unicodeScalars.filter { !forbiddenChars.contains($0) }
|
||||||
|
return String(String.UnicodeScalarView(passed))
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeCharacters(from: String) -> String {
|
||||||
|
return removeCharacters(from: CharacterSet(charactersIn: from))
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeTrailingWhitespace() -> String {
|
||||||
|
var newString = self
|
||||||
|
|
||||||
|
while newString.last?.isWhitespace == true {
|
||||||
|
newString = String(newString.dropLast())
|
||||||
|
}
|
||||||
|
|
||||||
|
return newString
|
||||||
|
}
|
||||||
|
|
||||||
|
func colorComponent() -> (alpha: String, red: String, green: String, blue: String) {
|
||||||
|
var alpha: String = "FF"
|
||||||
|
var red: String
|
||||||
|
var green: String
|
||||||
|
var blue: String
|
||||||
|
|
||||||
|
var colorClean = self
|
||||||
|
.replacingOccurrences(of: "#", with: "")
|
||||||
|
.replacingOccurrences(of: "0x", with: "")
|
||||||
|
|
||||||
|
if colorClean.count == 8 {
|
||||||
|
alpha = String(colorClean.prefix(2))
|
||||||
|
colorClean = String(colorClean.dropFirst(2))
|
||||||
|
}
|
||||||
|
|
||||||
|
red = String(colorClean.prefix(2))
|
||||||
|
colorClean = String(colorClean.dropFirst(2))
|
||||||
|
green = String(colorClean.prefix(2))
|
||||||
|
colorClean = String(colorClean.dropFirst(2))
|
||||||
|
blue = String(colorClean.prefix(2))
|
||||||
|
return (alpha: alpha, red: red, green: green, blue: blue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Sequence
|
||||||
|
|
||||||
|
extension Sequence where Iterator.Element: Hashable {
|
||||||
|
public func unique() -> [Iterator.Element] {
|
||||||
|
var seen: [Iterator.Element: Bool] = [:]
|
||||||
|
return self.filter { seen.updateValue(true, forKey: $0) == nil }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
41
Sources/ColorToolCore/ColorExtensionGenerator.swift
Normal file
41
Sources/ColorToolCore/ColorExtensionGenerator.swift
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// ColorExtensionGenerator.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 20/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct ColorExtensionGenerator {
|
||||||
|
|
||||||
|
let colors: [GenColor]
|
||||||
|
let extensionClassname: String
|
||||||
|
let isUIColorExtension: Bool
|
||||||
|
|
||||||
|
func getHeader() -> String {
|
||||||
|
"""
|
||||||
|
// Generated from ColorToolCore at \(Date())
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
53
Sources/ColorToolCore/ColorToolError.swift
Normal file
53
Sources/ColorToolCore/ColorToolError.swift
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// ColorToolError.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 20/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum ColorToolError: Error {
|
||||||
|
case badFormat(String)
|
||||||
|
case writeAsset(String)
|
||||||
|
case writeExtension(String, String)
|
||||||
|
case fileNotExists(String)
|
||||||
|
case badColorDefinition(String, String)
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .badFormat(let info):
|
||||||
|
return """
|
||||||
|
[ColorTool]
|
||||||
|
Bad line format: \(info). Accepted format are:
|
||||||
|
- colorName="#RGB/#ARGB"
|
||||||
|
- colorName "#RGB/#ARGB"
|
||||||
|
- colorName "#RGB/#ARGB" "#RGB/#ARGB"
|
||||||
|
"""
|
||||||
|
|
||||||
|
case .writeAsset(let info):
|
||||||
|
return """
|
||||||
|
[ColorTool]
|
||||||
|
An error occured while writing color in Xcasset: \(info)
|
||||||
|
"""
|
||||||
|
|
||||||
|
case .writeExtension(let filename, let info):
|
||||||
|
return """
|
||||||
|
[ColorTool]
|
||||||
|
An error occured while writing extension in \(filename): \(info)
|
||||||
|
"""
|
||||||
|
|
||||||
|
case .fileNotExists(let filename):
|
||||||
|
return """
|
||||||
|
[ColorTool]
|
||||||
|
File \(filename) does not exists
|
||||||
|
"""
|
||||||
|
|
||||||
|
case .badColorDefinition(let lightColor, let darkColor):
|
||||||
|
return """
|
||||||
|
[ColorTool]
|
||||||
|
One of these two colors has invalid synthax: -\(lightColor)- or -\(darkColor)-
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
Sources/ColorToolCore/ColorXcassetHelper.swift
Normal file
40
Sources/ColorToolCore/ColorXcassetHelper.swift
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
//
|
||||||
|
// ColorXcassetHelper.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 20/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CLIToolCore
|
||||||
|
|
||||||
|
struct ColorXcassetHelper {
|
||||||
|
|
||||||
|
let xcassetsPath: String
|
||||||
|
let colors: [GenColor]
|
||||||
|
|
||||||
|
func generateXcassetColors() {
|
||||||
|
colors.forEach {
|
||||||
|
generateColorSetAssets(from: $0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate ColorSet in XCAssets file
|
||||||
|
private func generateColorSetAssets(from color: GenColor) {
|
||||||
|
// Create ColorSet
|
||||||
|
let colorSetPath = "\(xcassetsPath)/Colors/\(color.name).colorset"
|
||||||
|
Shell.shell("mkdir", "-p", "\(colorSetPath)")
|
||||||
|
|
||||||
|
// Create Contents.json in ColorSet
|
||||||
|
let contentsJsonPath = "\(colorSetPath)/Contents.json"
|
||||||
|
Shell.shell("touch", "\(contentsJsonPath)")
|
||||||
|
|
||||||
|
// Write content in Contents.json
|
||||||
|
let contentsJsonPathURL = URL(fileURLWithPath: contentsJsonPath)
|
||||||
|
do {
|
||||||
|
try color.contentsJSON().write(to: contentsJsonPathURL, atomically: true, encoding: .utf8)
|
||||||
|
} catch (let error) {
|
||||||
|
ColorTool.exit(withError: ColorToolError.writeAsset(error.localizedDescription))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
90
Sources/ColorToolCore/GenColor.swift
Normal file
90
Sources/ColorToolCore/GenColor.swift
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
//
|
||||||
|
// GenColor.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 20/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct GenColor {
|
||||||
|
let name: String
|
||||||
|
let light: String
|
||||||
|
let dark: String
|
||||||
|
|
||||||
|
// Generate Contents.json content
|
||||||
|
func contentsJSON() -> String {
|
||||||
|
let lightARGB = light.colorComponent()
|
||||||
|
let darkARGB = dark.colorComponent()
|
||||||
|
|
||||||
|
let allComponents = [
|
||||||
|
lightARGB.alpha, lightARGB.red, lightARGB.green, lightARGB.blue,
|
||||||
|
darkARGB.alpha, darkARGB.red, darkARGB.green, darkARGB.blue
|
||||||
|
].map {
|
||||||
|
$0.isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
guard allComponents.contains(true) == false else {
|
||||||
|
ColorTool.exit(withError: ColorToolError.badColorDefinition(light, dark))
|
||||||
|
}
|
||||||
|
|
||||||
|
return """
|
||||||
|
{
|
||||||
|
"colors": [
|
||||||
|
{
|
||||||
|
"color": {
|
||||||
|
"color-space": "srgb",
|
||||||
|
"components": {
|
||||||
|
"alpha": "0x\(lightARGB.alpha)",
|
||||||
|
"blue": "0x\(lightARGB.blue)",
|
||||||
|
"green": "0x\(lightARGB.green)",
|
||||||
|
"red": "0x\(lightARGB.red)",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom": "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances": [
|
||||||
|
{
|
||||||
|
"appearance": "luminosity",
|
||||||
|
"value": "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color": {
|
||||||
|
"color-space": "srgb",
|
||||||
|
"components": {
|
||||||
|
"alpha": "0x\(darkARGB.alpha)",
|
||||||
|
"blue": "0x\(darkARGB.blue)",
|
||||||
|
"green": "0x\(darkARGB.green)",
|
||||||
|
"red": "0x\(darkARGB.red)",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom": "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info": {
|
||||||
|
"author": "xcode",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
func getColorProperty() -> String {
|
||||||
|
"""
|
||||||
|
/// Color \(name) is \(light) (light) or \(dark) (dark)"
|
||||||
|
@objc var \(name): UIColor {
|
||||||
|
UIColor(named: "\(name)")!
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
func getColorStaticProperty() -> String {
|
||||||
|
"""
|
||||||
|
/// Color \(name) is \(light) (light) or \(dark) (dark)"
|
||||||
|
static var \(name): UIColor {
|
||||||
|
UIColor(named: "\(name)")!
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
165
Sources/ColorToolCore/main.swift
Normal file
165
Sources/ColorToolCore/main.swift
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
//
|
||||||
|
// main.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 20/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CLIToolCore
|
||||||
|
import ArgumentParser
|
||||||
|
|
||||||
|
enum ColorStyle: String, Decodable {
|
||||||
|
case light
|
||||||
|
case all
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ColorTool: ParsableCommand {
|
||||||
|
static let defaultExtensionName = "UIColor"
|
||||||
|
static let assetsColorsFolderName = "Colors"
|
||||||
|
|
||||||
|
@Flag(name: .customShort("f"), help: "Should force generation")
|
||||||
|
var forceGeneration = false
|
||||||
|
|
||||||
|
@Argument(help: "Input files where colors ared defined.")
|
||||||
|
var inputFile: String
|
||||||
|
|
||||||
|
@Option(help: "Color style to generate: light for light colors only, or all for dark and light colors")
|
||||||
|
var style: String
|
||||||
|
|
||||||
|
@Option(help: "Path of xcassets where to generate colors")
|
||||||
|
var xcassetsPath: String
|
||||||
|
|
||||||
|
@Option(help: "Path where to generate the extension.")
|
||||||
|
var extensionOutputPath: String
|
||||||
|
|
||||||
|
@Option(help: "Extension name. If not specified, it will generate an UIFont extension")
|
||||||
|
var extensionName: String = Self.defaultExtensionName
|
||||||
|
|
||||||
|
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+ColorsMyApp.swift")
|
||||||
|
var extensionSuffix: String = ""
|
||||||
|
|
||||||
|
var colorStyle: ColorStyle { ColorStyle(rawValue: style) ?? .all }
|
||||||
|
var extensionFileName: String { "\(extensionName)+Font\(extensionSuffix).swift" }
|
||||||
|
var extensionFilePath: String { "\(extensionOutputPath)/\(extensionFileName)" }
|
||||||
|
|
||||||
|
public func run() throws {
|
||||||
|
print("[ColorTool] Starting colors generation")
|
||||||
|
|
||||||
|
print("[ColorTool] Will use inputFile \(inputFile) to generate \(colorStyle) colors in xcassets \(xcassetsPath)")
|
||||||
|
print("[ColorTool] Extension will be \(extensionFilePath)")
|
||||||
|
|
||||||
|
|
||||||
|
// Check if needed to regenerate
|
||||||
|
guard GeneratorChecker.shouldGenerate(force: forceGeneration, inputFilePath: inputFile, extensionFilePath: extensionFilePath) else {
|
||||||
|
print("[ColorTool] Colors are already up to date :) ")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
print("[ColorTool] Will generate colors")
|
||||||
|
|
||||||
|
// Check if Xcasset exists
|
||||||
|
let fileManager = FileManager()
|
||||||
|
guard fileManager.fileExists(atPath: xcassetsPath) else {
|
||||||
|
ColorTool.exit(withError: ColorToolError.fileNotExists(xcassetsPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete current colors
|
||||||
|
Shell.shell("rm", "-rf", "\(xcassetsPath)/Colors/*")
|
||||||
|
|
||||||
|
// Get colors
|
||||||
|
let colorsToGen = getColorsGen()
|
||||||
|
|
||||||
|
// Generate all colors in xcassets
|
||||||
|
let colorAssetHelper = ColorXcassetHelper(xcassetsPath: xcassetsPath, colors: colorsToGen)
|
||||||
|
colorAssetHelper.generateXcassetColors()
|
||||||
|
|
||||||
|
// Generate extension
|
||||||
|
let extensionGenerator = ColorExtensionGenerator(colors: colorsToGen,
|
||||||
|
extensionClassname: 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) {
|
||||||
|
ColorTool.exit(withError: ColorToolError.writeExtension(extensionFilePath, error.localizedDescription))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getColorsGen() -> [GenColor] {
|
||||||
|
// Get content of input file
|
||||||
|
let inputFileContent = try! String(contentsOfFile: inputFile, encoding: .utf8)
|
||||||
|
let colorsByLines = inputFileContent.components(separatedBy: .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 {
|
||||||
|
ColorTool.exit(withError: ColorToolError.badFormat(colorLine))
|
||||||
|
}
|
||||||
|
|
||||||
|
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]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Helpers
|
||||||
|
|
||||||
|
private func isUIColorExtension() -> Bool {
|
||||||
|
extensionName == Self.defaultExtensionName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorTool.main()
|
||||||
|
|
||||||
|
/*
|
||||||
|
Command samples:
|
||||||
|
|
||||||
|
1. UIColor extension without suffix
|
||||||
|
swift run -c release ColorToolCore -f ./SampleFiles/Colors/sampleColors1.txt --style all --xcassets-path "./SampleFiles/Colors/colors.xcassets" --extension-output-path "./SampleFiles/Colors/Generated/" --extension-name "UIColor"
|
||||||
|
|
||||||
|
2. UIColor extension with custom suffix
|
||||||
|
swift run -c release ColorToolCore -f ./SampleFiles/Colors/sampleColors1.txt --style all --xcassets-path "./SampleFiles/Colors/colors.xcassets" --extension-output-path "./SampleFiles/Colors/Generated/" --extension-name "UIColor" --extension-suffix "SampleApp"
|
||||||
|
|
||||||
|
3. Custom extension with only light theme colors (R2Color)
|
||||||
|
swift run -c release ColorToolCore -f ./SampleFiles/Colors/sampleColors1.txt --style light --xcassets-path "./SampleFiles/Colors/colors.xcassets" --extension-output-path "./SampleFiles/Colors/Generated/" --extension-name "R2Color"
|
||||||
|
*/
|
@ -1,26 +0,0 @@
|
|||||||
//
|
|
||||||
// File.swift
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Created by Thibaut Schmitt on 13/12/2021.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
extension String {
|
|
||||||
func removeCharacters(from forbiddenChars: CharacterSet) -> String {
|
|
||||||
let passed = self.unicodeScalars.filter { !forbiddenChars.contains($0) }
|
|
||||||
return String(String.UnicodeScalarView(passed))
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeCharacters(from: String) -> String {
|
|
||||||
return removeCharacters(from: CharacterSet(charactersIn: from))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Sequence where Iterator.Element: Hashable {
|
|
||||||
func unique() -> [Iterator.Element] {
|
|
||||||
var seen: [Iterator.Element: Bool] = [:]
|
|
||||||
return self.filter { seen.updateValue(true, forKey: $0) == nil }
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,12 +16,16 @@ enum FontToolError: Error {
|
|||||||
switch self {
|
switch self {
|
||||||
case .fcScan(let path, let code, let output):
|
case .fcScan(let path, let code, let output):
|
||||||
return """
|
return """
|
||||||
|
[FontTool]
|
||||||
Error while getting fontName (fc-scan --format %{postscriptname} \(path).
|
Error while getting fontName (fc-scan --format %{postscriptname} \(path).
|
||||||
fc-scan exit with \(code) and output is: \(output ?? "no output")
|
fc-scan exit with \(code) and output is: \(output ?? "no output")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
case .inputFolderNotFound(let inputFolder):
|
case .inputFolderNotFound(let inputFolder):
|
||||||
return "Input folder not found: \(inputFolder)"
|
return """
|
||||||
|
[ColorTool]
|
||||||
|
Input folder not found: \(inputFolder)
|
||||||
|
"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,11 @@ import Foundation
|
|||||||
import CLIToolCore
|
import CLIToolCore
|
||||||
import ArgumentParser
|
import ArgumentParser
|
||||||
|
|
||||||
|
/*
|
||||||
|
Lire l'infoPlist et check si les fonts dedans sont les memes que celles à générer
|
||||||
|
*/
|
||||||
|
|
||||||
|
//swift run -c release FontToolCore ./SampleFiles/Fonts --extension-output-path ~/Desktop --extension-name R2Font
|
||||||
struct FontTool: ParsableCommand {
|
struct FontTool: ParsableCommand {
|
||||||
static let defaultExtensionName = "UIFont"
|
static let defaultExtensionName = "UIFont"
|
||||||
|
|
||||||
@ -22,7 +27,7 @@ struct FontTool: ParsableCommand {
|
|||||||
var extensionName: String = Self.defaultExtensionName
|
var extensionName: String = Self.defaultExtensionName
|
||||||
|
|
||||||
public func run() throws {
|
public func run() throws {
|
||||||
print("[FontTool] Starting font generation")
|
print("[FontTool] Starting fonts generation")
|
||||||
|
|
||||||
let fontsData = FontToolHelper.getFontsData(fromInputFolder: inputFolder)
|
let fontsData = FontToolHelper.getFontsData(fromInputFolder: inputFolder)
|
||||||
|
|
||||||
@ -41,7 +46,7 @@ struct FontTool: ParsableCommand {
|
|||||||
print("Info.plist information:")
|
print("Info.plist information:")
|
||||||
print("\(generatePlistUIAppFonts(fontsNames: fontsData.fontsNames))")
|
print("\(generatePlistUIAppFonts(fontsNames: fontsData.fontsNames))")
|
||||||
|
|
||||||
print("[FontTool] Font generated")
|
print("[FontTool] Fonts generated")
|
||||||
}
|
}
|
||||||
|
|
||||||
private func generateExtensionFile(_ args: String...) {
|
private func generateExtensionFile(_ args: String...) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user