Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
78be15d57d | |||
d6c4702390 | |||
1e073af5df | |||
188178fe6a | |||
c31d0b1618 | |||
b662fc64f3 | |||
9ab7e74991 | |||
fc427733ee | |||
5a3d273acc | |||
a7a850799d | |||
7d3652f1f9 | |||
41733d2680 | |||
6203700b0c |
@ -1,78 +0,0 @@
|
|||||||
<?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>
|
|
@ -1,78 +0,0 @@
|
|||||||
<?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>
|
|
@ -1,78 +0,0 @@
|
|||||||
<?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 = "Imagium"
|
|
||||||
BuildableName = "Imagium"
|
|
||||||
BlueprintName = "Imagium"
|
|
||||||
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 = "Imagium"
|
|
||||||
BuildableName = "Imagium"
|
|
||||||
BlueprintName = "Imagium"
|
|
||||||
ReferencedContainer = "container:">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</LaunchAction>
|
|
||||||
<ProfileAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
||||||
savedToolIdentifier = ""
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
debugDocumentVersioning = "YES">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "Imagium"
|
|
||||||
BuildableName = "Imagium"
|
|
||||||
BlueprintName = "Imagium"
|
|
||||||
ReferencedContainer = "container:">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</ProfileAction>
|
|
||||||
<AnalyzeAction
|
|
||||||
buildConfiguration = "Debug">
|
|
||||||
</AnalyzeAction>
|
|
||||||
<ArchiveAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
revealArchiveInOrganizer = "YES">
|
|
||||||
</ArchiveAction>
|
|
||||||
</Scheme>
|
|
@ -1,237 +0,0 @@
|
|||||||
<?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>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "StringToolCore"
|
|
||||||
BuildableName = "StringToolCore"
|
|
||||||
BlueprintName = "StringToolCore"
|
|
||||||
ReferencedContainer = "container:">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "TwineToolCore"
|
|
||||||
BuildableName = "TwineToolCore"
|
|
||||||
BlueprintName = "TwineToolCore"
|
|
||||||
ReferencedContainer = "container:">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "Strings"
|
|
||||||
BuildableName = "Strings"
|
|
||||||
BlueprintName = "Strings"
|
|
||||||
ReferencedContainer = "container:">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "FontTool"
|
|
||||||
BuildableName = "FontTool"
|
|
||||||
BlueprintName = "FontTool"
|
|
||||||
ReferencedContainer = "container:">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "Imagium"
|
|
||||||
BuildableName = "Imagium"
|
|
||||||
BlueprintName = "Imagium"
|
|
||||||
ReferencedContainer = "container:">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "ToolCore"
|
|
||||||
BuildableName = "ToolCore"
|
|
||||||
BlueprintName = "ToolCore"
|
|
||||||
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 = "Imagium"
|
|
||||||
BuildableName = "Imagium"
|
|
||||||
BlueprintName = "Imagium"
|
|
||||||
ReferencedContainer = "container:">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
<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">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "Imagium"
|
|
||||||
BuildableName = "Imagium"
|
|
||||||
BlueprintName = "Imagium"
|
|
||||||
ReferencedContainer = "container:">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</ProfileAction>
|
|
||||||
<AnalyzeAction
|
|
||||||
buildConfiguration = "Debug">
|
|
||||||
</AnalyzeAction>
|
|
||||||
<ArchiveAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
revealArchiveInOrganizer = "YES">
|
|
||||||
</ArchiveAction>
|
|
||||||
</Scheme>
|
|
@ -34,6 +34,34 @@
|
|||||||
ReferencedContainer = "container:">
|
ReferencedContainer = "container:">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildActionEntry>
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ToolCore"
|
||||||
|
BuildableName = "ToolCore"
|
||||||
|
BlueprintName = "ToolCore"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ResgenSwift_ResgenSwift"
|
||||||
|
BuildableName = "ResgenSwift_ResgenSwift"
|
||||||
|
BlueprintName = "ResgenSwift_ResgenSwift"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
</BuildActionEntries>
|
</BuildActionEntries>
|
||||||
</BuildAction>
|
</BuildAction>
|
||||||
<TestAction
|
<TestAction
|
||||||
@ -74,6 +102,20 @@
|
|||||||
ReferencedContainer = "container:">
|
ReferencedContainer = "container:">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
|
<CommandLineArguments>
|
||||||
|
<CommandLineArgument
|
||||||
|
argument = "generate"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</CommandLineArgument>
|
||||||
|
<CommandLineArgument
|
||||||
|
argument = ""$(PROJECT_DIR)/../SampleFiles/resgenConfiguration.yml""
|
||||||
|
isEnabled = "YES">
|
||||||
|
</CommandLineArgument>
|
||||||
|
<CommandLineArgument
|
||||||
|
argument = "--project-directory "$(PROJECT_DIR)""
|
||||||
|
isEnabled = "YES">
|
||||||
|
</CommandLineArgument>
|
||||||
|
</CommandLineArguments>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Release"
|
||||||
|
34
CHANGELOG.md
34
CHANGELOG.md
@ -0,0 +1,34 @@
|
|||||||
|
# v1.2 - Architecture generation
|
||||||
|
|
||||||
|
## New
|
||||||
|
- New section in configuration file: `architecture`. Define your ressources accessors achitecture and let ResgenSwift generate it for you. Check out Readme to know more.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Errors and Warnings are now shown in Xcode Issue Navigator
|
||||||
|
|
||||||
|
---
|
||||||
|
# v1.1 - SwiftUI compatibility
|
||||||
|
|
||||||
|
## New
|
||||||
|
- Update plist `UIAppFonts` when generated fonts (use plistBuddy)
|
||||||
|
- New parameter: `infoPlistPaths`
|
||||||
|
- Generate SwiftUI extensions for colors, fonts and images
|
||||||
|
- New parameter: `extensionNameSwiftUI`
|
||||||
|
- Adding Makefile to install, unsintall and create man page.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
Fix SwiftLint rule `trailing_newline`
|
||||||
|
|
||||||
|
---
|
||||||
|
# v1.0 - Configuration file
|
||||||
|
|
||||||
|
## Major
|
||||||
|
- A new command has been added: `generate`. Instead of runnning every single command, it will run all necessary command based on a `yaml` configuration file. Check out Readme to know more.
|
||||||
|
|
||||||
|
## Minors
|
||||||
|
- Code refactoring
|
||||||
|
- Huge performance improvements
|
||||||
|
- Readme.md update
|
||||||
|
- Add option to generate static properties/methods (`staticMembers`)
|
||||||
|
- Add option to specify the project directory (`--project-directory`). It allows to run ResgenSwift from anywhere
|
||||||
|
- Add `install.sh` script to install ResgenSwift in `/usr/local/bin`
|
||||||
|
4
Jenkinsfile
vendored
4
Jenkinsfile
vendored
@ -1,6 +1,8 @@
|
|||||||
library "openiumpipeline"
|
library "openiumpipeline"
|
||||||
|
|
||||||
//env.DEVELOPER_DIR="/Applications/Xcode_12.4.app/Contents/Developer"
|
env.DEVELOPER_DIR= "/Applications/Xcode-14.3.0.app/Contents/Developer"
|
||||||
//env.SIMULATOR_DEVICE_TYPES="iPad--7th-generation-"
|
//env.SIMULATOR_DEVICE_TYPES="iPad--7th-generation-"
|
||||||
|
env.IS_PACKAGE_SWIFT=1
|
||||||
|
env.TARGETS_MACOS=1
|
||||||
|
|
||||||
iOSpipeline()
|
iOSpipeline()
|
||||||
|
63
Makefile
Normal file
63
Makefile
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
SHELL = /bin/zsh
|
||||||
|
|
||||||
|
#INSTALL_DIR ?= /usr/local/bin
|
||||||
|
INSTALL_DIR = /tmp/ResgenYolo
|
||||||
|
|
||||||
|
MAN_DIR := /usr/local/share/man
|
||||||
|
MAN_PAGE_NAME = resgen-swift.1
|
||||||
|
REPO_DIR = $(shell pwd)
|
||||||
|
BUILD_DIR = $(REPO_DIR)/.build
|
||||||
|
|
||||||
|
#
|
||||||
|
# Man pages
|
||||||
|
#
|
||||||
|
|
||||||
|
# create-man-files:
|
||||||
|
# swift package plugin generate-manual
|
||||||
|
# cp $(BUILDDIR)/plugins/GenerateManualPlugin/outputs/ResgenSwift/resgen-swift.1 $(REPODIR)/man/resgen-swift.1
|
||||||
|
|
||||||
|
# install-man-files:
|
||||||
|
# mkdir -p ${DESTDIR}${mandir}/man1
|
||||||
|
# cp $(REPODIR)/man/resgen-swift.1 ${DESTDIR}${mandir}/man1/resgen-swift.1
|
||||||
|
|
||||||
|
create-and-install-man-files:
|
||||||
|
swift package plugin generate-manual
|
||||||
|
mkdir -p ${MAN_DIR}/man1
|
||||||
|
cp $(BUILD_DIR)/plugins/GenerateManualPlugin/outputs/ResgenSwift/${MAN_PAGE_NAME} ${MAN_DIR}/man1/${MAN_PAGE_NAME}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build and install
|
||||||
|
#
|
||||||
|
|
||||||
|
build-debug:
|
||||||
|
@swift build \
|
||||||
|
-c debug \
|
||||||
|
--build-path "$(BUILD_DIR)"
|
||||||
|
|
||||||
|
build-release:
|
||||||
|
@swift build \
|
||||||
|
-c release \
|
||||||
|
--build-path "$(BUILD_DIR)"
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install: build-release
|
||||||
|
@install -d "$(INSTALL_DIR)"
|
||||||
|
@install "$(wildcard $(BUILD_DIR)/**/release/ResgenSwift)" "$(INSTALL_DIR)/resgen-swift"
|
||||||
|
@make create-and-install-man-files
|
||||||
|
|
||||||
|
#
|
||||||
|
# Uninstall and cleaning
|
||||||
|
#
|
||||||
|
|
||||||
|
.PHONY: uninstall
|
||||||
|
uninstall:
|
||||||
|
@rm -rf "$(INSTALL_DIR)/resgen-swift"
|
||||||
|
@rm -rf ${MAN_DIR}/man1/${MAN_PAGE_NAME}
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
distclean:
|
||||||
|
@rm -f $(BUILD_DIR)/release
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean: distclean
|
||||||
|
@rm -rf $(BUILD_DIR)
|
@ -1,16 +1,23 @@
|
|||||||
{
|
{
|
||||||
"object": {
|
"pins" : [
|
||||||
"pins": [
|
{
|
||||||
{
|
"identity" : "swift-argument-parser",
|
||||||
"package": "swift-argument-parser",
|
"kind" : "remoteSourceControl",
|
||||||
"repositoryURL": "https://github.com/apple/swift-argument-parser",
|
"location" : "https://github.com/apple/swift-argument-parser",
|
||||||
"state": {
|
"state" : {
|
||||||
"branch": null,
|
"revision" : "9f39744e025c7d377987f30b03770805dcb0bcd1",
|
||||||
"revision": "e1465042f195f374b94f915ba8ca49de24300a0d",
|
"version" : "1.1.4"
|
||||||
"version": "1.0.2"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
},
|
||||||
},
|
{
|
||||||
"version": 1
|
"identity" : "yams",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/jpsim/Yams.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "01835dc202670b5bb90d07f3eae41867e9ed29f6",
|
||||||
|
"version" : "5.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version" : 2
|
||||||
}
|
}
|
||||||
|
@ -1,53 +1,31 @@
|
|||||||
// swift-tools-version:5.3
|
// swift-tools-version:5.6
|
||||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||||
|
|
||||||
import PackageDescription
|
import PackageDescription
|
||||||
|
|
||||||
let package = Package(
|
let package = Package(
|
||||||
name: "ResgenSwift",
|
name: "ResgenSwift",
|
||||||
platforms: [.macOS(.v10_12)],
|
platforms: [.macOS(.v12)],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
// Dependencies declare other packages that this package depends on.
|
// Dependencies declare other packages that this package depends on.
|
||||||
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0")
|
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0"),
|
||||||
|
.package(url: "https://github.com/jpsim/Yams.git", from: "5.0.1")
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||||
// 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(
|
.executableTarget(
|
||||||
name: "ResgenSwift",
|
name: "ResgenSwift",
|
||||||
dependencies: ["FontTool", "ColorTool", "Strings", "Imagium"]
|
|
||||||
),
|
|
||||||
.target(
|
|
||||||
name: "FontTool",
|
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"ToolCore",
|
"ToolCore",
|
||||||
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
.product(name: "ArgumentParser", package: "swift-argument-parser"),
|
||||||
]
|
"Yams"
|
||||||
),
|
|
||||||
.target(
|
|
||||||
name: "ColorTool",
|
|
||||||
dependencies: [
|
|
||||||
"ToolCore",
|
|
||||||
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
|
||||||
]
|
|
||||||
),
|
|
||||||
.target(
|
|
||||||
name: "Strings",
|
|
||||||
dependencies: [
|
|
||||||
"ToolCore",
|
|
||||||
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
|
||||||
],
|
|
||||||
sources: ["."] // Force include all subdirectories
|
|
||||||
),
|
|
||||||
.target(
|
|
||||||
name: "Imagium",
|
|
||||||
dependencies: [
|
|
||||||
"ToolCore",
|
|
||||||
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
|
||||||
// Helper targets
|
// Helper targets
|
||||||
.target(name: "ToolCore"),
|
.target(name: "ToolCore"),
|
||||||
|
|
||||||
// Test targets
|
// Test targets
|
||||||
.testTarget(
|
.testTarget(
|
||||||
name: "ResgenSwiftTests",
|
name: "ResgenSwiftTests",
|
||||||
|
283
README.md
283
README.md
@ -4,18 +4,22 @@ ResgenSwift is a package, fully written in Swift, to help you automatize ressour
|
|||||||
|
|
||||||
> 🧐 For all commands, see samples files in `SampleFiles`
|
> 🧐 For all commands, see samples files in `SampleFiles`
|
||||||
|
|
||||||
# Fonts
|
## Fonts
|
||||||
|
|
||||||
Font generator generates an extension of `UIFont` (or a custom class). It also prints `UIAppFonts` to put in your project `.plist`.
|
Font generator generates an extension of `UIFont` and `Font` (or custom classes). It also prints content of `UIAppFonts` from your project `.plist`. If project `.plist` is specified, it will update `UIAppFonts` content of all `.plist`.
|
||||||
iOS required to use the **real name** of the font, this name can be different from its filename. To get the **real name**, it uses `fc-scan`.
|
|
||||||
|
iOS required to use the **real name** of the font, this name can be different from its filename. To get the **real name**, it uses `fc-scan`. So, be sure that the `$PATH` contains path of `fc-scan`.
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
|
|
||||||
```
|
```sh
|
||||||
swift run -c release FontTool $FORCE_FLAG "./Fonts/fonts.txt" \
|
swift run -c release ResgenSwift fonts $FORCE_FLAG "./Fonts/fonts.txt" \
|
||||||
--extension-output-path "./Fonts/Generated" \
|
--extension-output-path "./Fonts/Generated" \
|
||||||
--extension-name "AppFont" \
|
--extension-name "AppFont" \
|
||||||
--extension-suffix "GreatApp"
|
--extension-name-swift-ui "SUIAppFont" \
|
||||||
|
--extension-suffix "GreatApp" \
|
||||||
|
--static-members true \
|
||||||
|
--info-plist-paths "./path/one/to/Info.plist ./path/two/to/Info.plist"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
@ -23,23 +27,26 @@ swift run -c release FontTool $FORCE_FLAG "./Fonts/fonts.txt" \
|
|||||||
1. `-f`: force generation
|
1. `-f`: force generation
|
||||||
2. Font input folder, it will search for every `.ttf` and `.otf` files specified in `fonts.txt`
|
2. Font input folder, it will search for every `.ttf` and `.otf` files specified in `fonts.txt`
|
||||||
3. `--extension-output-path`: path where to generate generated extension
|
3. `--extension-output-path`: path where to generate generated extension
|
||||||
4. `--extension-name` *(optional)* : name of thee class to add the extension
|
4. `--extension-name` *(optional)* : name of the class to add UIKit getters
|
||||||
5. `--extension-suffix` *(optional)* : additional text which is added to the filename (ex: `AppFont+GreatApp.swift`)
|
5. `--extension-name-swift-ui` *(optional)* : name of the class to add SwiftUI getters
|
||||||
|
6. `--extension-suffix` *(optional)* : additional text which is added to the filename (ex: `AppFont+GreatApp.swift`)
|
||||||
> ⚠️ If extension name is not set or is `UIFont`, it will generate static property on `UIFont` instead of method in your custom class.
|
7. `--static-members` *(optional)*: generate static properties or not
|
||||||
|
8. `--info-plist-paths` *(optional)*: array of `.plist`, you can specify multiple `Info.plist` for multiple targets
|
||||||
|
|
||||||
|
|
||||||
# Colors
|
## Colors
|
||||||
|
|
||||||
Colors generator generates an extension of `UIColor` (or a custom class) along with colorsets in specified xcassets.
|
Colors generator generates an extension of `UIColor` (or a custom class) along with colorsets in specified xcassets.
|
||||||
|
|
||||||
```
|
```sh
|
||||||
swift run -c release ColorTool $FORCE_FLAG "./Colors/colors.txt" \
|
swift run -c release ResgenSwift colors $FORCE_FLAG "./Colors/colors.txt" \
|
||||||
--style all \
|
--style all \
|
||||||
--xcassets-path "./Colors/colors.xcassets" \
|
--xcassets-path "./Colors/colors.xcassets" \
|
||||||
--extension-output-path "./Colors/Generated/" \
|
--extension-output-path "./Colors/Generated/" \
|
||||||
--extension-name "AppColor" \
|
--extension-name "AppColor" \
|
||||||
--extension-suffix "GreatApp"
|
--extension-name-swift-ui "SUIAppColor" \
|
||||||
|
--extension-suffix "GreatApp" \
|
||||||
|
--static-members true
|
||||||
```
|
```
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
@ -48,25 +55,25 @@ swift run -c release ColorTool $FORCE_FLAG "./Colors/colors.txt" \
|
|||||||
2. Input colors file
|
2. Input colors file
|
||||||
3. `--style` can be `all` or `light`
|
3. `--style` can be `all` or `light`
|
||||||
4. `--extension-output-path`: path where to generate generated extension
|
4. `--extension-output-path`: path where to generate generated extension
|
||||||
5. `--extension-name` *(optional)* : name of class to add the extension
|
5. `--extension-name` *(optional)* : name of the class to add UIKit getters
|
||||||
6. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppColor+GreatApp.swift`)
|
6. `--extension-name-swift-ui` *(optional)* : name of the class to add SwiftUI getters
|
||||||
|
7. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppColor+GreatApp.swift`)
|
||||||
|
8. `--static-members` *(optional)*: generate static properties or not
|
||||||
|
|
||||||
> ⚠️ If extension name is not set or is `UIColor`, it will generate static property on `UIColor`.
|
|
||||||
|
|
||||||
|
## Strings
|
||||||
# Strings
|
|
||||||
|
|
||||||
Strings command allows to generate `strings` files along with extensions to access those strings easily. It can do it 2 ways: Twine and Stringium. It is not recommended to use Twine except on legacy projects or while migrating to ResgenSwift, because it use https://github.com/openium/twine. Using Stringium is recommended because it does not required external dependency and allow more customisation.
|
Strings command allows to generate `strings` files along with extensions to access those strings easily. It can do it 2 ways: Twine and Stringium. It is not recommended to use Twine except on legacy projects or while migrating to ResgenSwift, because it use https://github.com/openium/twine. Using Stringium is recommended because it does not required external dependency and allow more customisation.
|
||||||
|
|
||||||
## Twine (not recommended)
|
### Twine (not recommended)
|
||||||
|
|
||||||
```
|
```sh
|
||||||
swift run -c release Strings twine $FORCE_FLAG "./Twine/strings.txt" \
|
swift run -c release ResgenSwift strings twine $FORCE_FLAG "./Twine/strings.txt" \
|
||||||
--output-path "./Twine/Generated" \
|
--output-path "./Twine/Generated" \
|
||||||
--langs "fr en en-us" \
|
--langs "fr en en-us" \
|
||||||
--default-lang "en" \
|
--default-lang "en" \
|
||||||
--extension-output-path "./Twine/Generated"
|
--extension-output-path "./Twine/Generated"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@ -76,16 +83,17 @@ swift run -c release Strings twine $FORCE_FLAG "./Twine/strings.txt" \
|
|||||||
4. `--default-lang`: default lang that will be in `Base.lproj`. It must be in `langs` as well
|
4. `--default-lang`: default lang that will be in `Base.lproj`. It must be in `langs` as well
|
||||||
4. `--extension-output-path`: path where to generate generated extension
|
4. `--extension-output-path`: path where to generate generated extension
|
||||||
|
|
||||||
## Stringium (recommended)
|
### Stringium (recommended)
|
||||||
|
|
||||||
```
|
```sh
|
||||||
swift run -c release Strings stringium $FORCE_FLAG "./Strings/strings.txt" \
|
swift run -c release ResgenSwift strings stringium $FORCE_FLAG "./Strings/strings.txt" \
|
||||||
--output-path "./Strings/Generated" \
|
--output-path "./Strings/Generated" \
|
||||||
--langs "fr en en-us" \
|
--langs "fr en en-us" \
|
||||||
--default-lang "en" \
|
--default-lang "en" \
|
||||||
--extension-output-path "./Strings/Generated" \
|
--extension-output-path "./Strings/Generated" \
|
||||||
--extension-name "AppString" \
|
--extension-name "AppString" \
|
||||||
--extension-suffix "GreatApp"
|
--extension-suffix "GreatApp" \
|
||||||
|
--static-members true
|
||||||
```
|
```
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
@ -97,19 +105,20 @@ swift run -c release Strings stringium $FORCE_FLAG "./Strings/strings.txt" \
|
|||||||
4. `--extension-output-path`: path where to generate generated extension
|
4. `--extension-output-path`: path where to generate generated extension
|
||||||
5. `--extension-name` *(optional)* : name of class to add the extension
|
5. `--extension-name` *(optional)* : name of class to add the extension
|
||||||
6. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppString+GreatApp.swift`)
|
6. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppString+GreatApp.swift`)
|
||||||
|
7. `--static-members` *(optional)*: generate static properties or not
|
||||||
|
|
||||||
> ⚠️ If extension name is not set or is `String`, it will generate static property on `String`.
|
|
||||||
|
|
||||||
# Tags
|
## Tags
|
||||||
|
|
||||||
Tags is also a subcommand of `Strings`. Input files are formatted the same way. Tags will generate properties which return exactly what is specified in the input file. It was designed to be used for analytics purpose and to be shared with any other platform to have the same analytics keys.
|
Tags is also a subcommand of `Strings`. Input files are formatted the same way. Tags will generate properties which return exactly what is specified in the input file. It was designed to be used for analytics purpose and to be shared with any other platform to have the same analytics keys.
|
||||||
|
|
||||||
```
|
```sh
|
||||||
swift run -c release Strings tags $FORCE_FLAG "./Tags/tags.txt" \
|
swift run -c release ResgenSwift strings tags $FORCE_FLAG "./Tags/tags.txt" \
|
||||||
--lang "ium" \
|
--lang "ium" \
|
||||||
--extension-output-path "./Tags/Generated" \
|
--extension-output-path "./Tags/Generated" \
|
||||||
--extension-name "AppTags" \
|
--extension-name "AppTags" \
|
||||||
--extension-suffix "GreatApp"
|
--extension-suffix "GreatApp" \
|
||||||
|
--static-members true
|
||||||
```
|
```
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
@ -120,19 +129,22 @@ swift run -c release Strings tags $FORCE_FLAG "./Tags/tags.txt" \
|
|||||||
4. `--extension-output-path`: path where to generate generated extension
|
4. `--extension-output-path`: path where to generate generated extension
|
||||||
5. `--extension-name` *(optional)* : name of class to add the extension
|
5. `--extension-name` *(optional)* : name of class to add the extension
|
||||||
6. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppTags+GreatApp.swift`)
|
6. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppTags+GreatApp.swift`)
|
||||||
|
7. `--static-members` *(optional)*: generate static properties or not
|
||||||
|
|
||||||
> ⚠️ If extension name is not set or is `Tags`, it will generate static property on `Tags`. This class may not exists in your project, just create an empty class named `Tags` is necessary.
|
> ⚠️ If extension name is not set or is `Tags`, it will generate the following typaloas `typealias Tags = String`.
|
||||||
|
|
||||||
# Images
|
## Images
|
||||||
|
|
||||||
Images generator will generate images assets along with extensions to access those images easily.
|
Images generator will generate images assets along with extensions to access those images easily.
|
||||||
|
|
||||||
```
|
```sh
|
||||||
swift run -c release Imagium $FORCE_FLAG "./Images/images.txt" \
|
swift run -c release ResgenSwift images $FORCE_FLAG "./Images/images.txt" \
|
||||||
--xcassets-path "./Images/app.xcassets" \
|
--xcassets-path "./Images/app.xcassets" \
|
||||||
--extension-output-path "./Images/Generated" \
|
--extension-output-path "./Images/Generated" \
|
||||||
--extension-name "AppImage" \
|
--extension-name "AppImage" \
|
||||||
--extension-suffix "GreatApp"
|
--extension-name-swift-ui "SUIAppImage" \
|
||||||
|
--extension-suffix "GreatApp" \
|
||||||
|
--static-members true
|
||||||
```
|
```
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
@ -141,11 +153,200 @@ swift run -c release Imagium $FORCE_FLAG "./Images/images.txt" \
|
|||||||
2. Input images definitions file
|
2. Input images definitions file
|
||||||
3. `--xcassets-path`: xcasset path where to generate imagesets
|
3. `--xcassets-path`: xcasset path where to generate imagesets
|
||||||
4. `--extension-output-path`: path where to generate generated extension
|
4. `--extension-output-path`: path where to generate generated extension
|
||||||
5. `--extension-name` *(optional)* : name of class to add the extension
|
5. `--extension-name` *(optional)* : name of the class to add UIKit getters
|
||||||
|
6. `--extension-name-swift-ui` *(optional)* : name of the class to add SwiftUI getters
|
||||||
6. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppImage+GreatApp.swift`)
|
6. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppImage+GreatApp.swift`)
|
||||||
|
7. `--static-members` *(optional)*: generate static properties or not
|
||||||
|
|
||||||
> ⚠️ If extension name is not set or is `UIImage`, it will generate static property on `UIImage`.
|
|
||||||
|
|
||||||
# TODO
|
## All at once
|
||||||
|
|
||||||
[ ] Allow static variable generation on custom extension
|
Another command exists to generate all ressources at the same time: `generate`. It use the following commands: `Fonts`, `Colors`, `Strings/Stringium`, `Strings/Tags`, `Images`.
|
||||||
|
|
||||||
|
All parameters can be specified in a configuration file in `Yaml`:
|
||||||
|
|
||||||
|
> Order of configuration types does not matter. Order them to fit your needs.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
colors:
|
||||||
|
-
|
||||||
|
inputFile: String
|
||||||
|
style: [light/all]
|
||||||
|
xcassetsPath: String
|
||||||
|
extensionOutputPath: String
|
||||||
|
extensionName: String?
|
||||||
|
extensionNameSwiftUI: String?
|
||||||
|
extensionSuffix: String?
|
||||||
|
staticMembers: Bool?
|
||||||
|
|
||||||
|
fonts:
|
||||||
|
-
|
||||||
|
inputFile: String
|
||||||
|
extensionOutputPath: String
|
||||||
|
extensionName: String?
|
||||||
|
extensionNameSwiftUI: String?
|
||||||
|
extensionSuffix: String?
|
||||||
|
staticMembers: Bool?
|
||||||
|
infoPlistPaths: [String]
|
||||||
|
|
||||||
|
images:
|
||||||
|
-
|
||||||
|
inputFile: String
|
||||||
|
xcassetsPath: String
|
||||||
|
extensionOutputPath: String
|
||||||
|
extensionName: String?
|
||||||
|
extensionNameSwiftUI: String?
|
||||||
|
extensionSuffix: String?
|
||||||
|
staticMembers: Bool?
|
||||||
|
|
||||||
|
strings:
|
||||||
|
-
|
||||||
|
inputFile: String
|
||||||
|
outputPath: String
|
||||||
|
langs: String
|
||||||
|
defaultLang: String
|
||||||
|
extensionOutputPath: String
|
||||||
|
extensionName: String?
|
||||||
|
extensionSuffix: String?
|
||||||
|
staticMembers: Bool?
|
||||||
|
|
||||||
|
tags:
|
||||||
|
-
|
||||||
|
inputFile: String
|
||||||
|
lang: String
|
||||||
|
extensionOutputPath: String
|
||||||
|
extensionName: String?
|
||||||
|
extensionSuffix: String?
|
||||||
|
staticMembers: Bool?
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple configurations
|
||||||
|
|
||||||
|
In some case, you may need to have 2 colors files in your projects. You will need 2 colors configurations. Every configuration type is an array and can contains as many configurations as you need.
|
||||||
|
|
||||||
|
Sample for 2 colors configurations:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
...
|
||||||
|
colors:
|
||||||
|
-
|
||||||
|
inputFile: String
|
||||||
|
style: [light/all]
|
||||||
|
xcassetsPath: String
|
||||||
|
extensionOutputPath: String
|
||||||
|
extensionName: String?
|
||||||
|
extensionNameSwiftUI: String?
|
||||||
|
extensionSuffix: String?
|
||||||
|
staticMembers: Bool?
|
||||||
|
-
|
||||||
|
inputFile: String
|
||||||
|
style: [light/all]
|
||||||
|
xcassetsPath: String
|
||||||
|
extensionOutputPath: String
|
||||||
|
extensionName: String?
|
||||||
|
extensionNameSwiftUI: String?
|
||||||
|
extensionSuffix: String?
|
||||||
|
staticMembers: Bool?
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
### No configuration
|
||||||
|
|
||||||
|
In some case, you may not need to generate tags for example. You must specified `tags` as an empty array :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
...
|
||||||
|
tags: []
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
### File architecture
|
||||||
|
|
||||||
|
ResgenSwift generate extension of classes. Those classes must exists in your project. You can create them yourself OR you can let ResgenSwift create them by specifying what you want. Do as follow:
|
||||||
|
|
||||||
|
```
|
||||||
|
architecture:
|
||||||
|
property: R *(required but not used)*
|
||||||
|
classname: R
|
||||||
|
path: ./path/to/generate
|
||||||
|
children:
|
||||||
|
- property: images
|
||||||
|
classname: R2Image
|
||||||
|
- property: strings
|
||||||
|
classname: R2String
|
||||||
|
- property: fonts
|
||||||
|
classname: R2Font
|
||||||
|
- property: images
|
||||||
|
classname: R2Image
|
||||||
|
- property: uikit
|
||||||
|
classname: R2UI
|
||||||
|
children:
|
||||||
|
- property: images
|
||||||
|
classname: R2UIImage
|
||||||
|
- property: fonts
|
||||||
|
classname: R2UIFont
|
||||||
|
- property: images
|
||||||
|
classname: R2UIImage
|
||||||
|
```
|
||||||
|
|
||||||
|
This will generate a file named as the architecture classname: `R.swift`. Based on the previous architecture, it will generate:
|
||||||
|
```
|
||||||
|
class R {
|
||||||
|
static let images = R2Image()
|
||||||
|
static let strings = R2String()
|
||||||
|
static let fonts = R2Font()
|
||||||
|
static let images = R2Image()
|
||||||
|
static let uikit = R2UI()
|
||||||
|
}
|
||||||
|
|
||||||
|
class R2Image {}
|
||||||
|
|
||||||
|
class R2String {}
|
||||||
|
|
||||||
|
class R2Font {}
|
||||||
|
|
||||||
|
class R2Image {}
|
||||||
|
|
||||||
|
class R2UI {
|
||||||
|
let images = R2UIImage()
|
||||||
|
let fonts = R2UIFont()
|
||||||
|
let images = R2UIImage()
|
||||||
|
}
|
||||||
|
|
||||||
|
class R2UIImage {}
|
||||||
|
|
||||||
|
class R2UIFont {}
|
||||||
|
|
||||||
|
class R2UIImage {}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```sh
|
||||||
|
swift run -c release ResgenSwift generate path/to/configuration.yml --project-directory ${PROJECT_DIR}
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ Every path in `configuration.yml` will be prepended by content of `--project-directory` if they are relative path (not starting with `/`)
|
||||||
|
|
||||||
|
|
||||||
|
## Binary usage
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
Run `make install`. Binary will be install in `/usr/local/bin`.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
resgen-swift generate path/to/configuration.yml --project-directory ${PROJECT_DIR}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Man page
|
||||||
|
|
||||||
|
Commands parameters and details can be find by running `resgen-swift --help`. If you prefer, a man page is also available. Run `man resgen-swift`. Man page is installed on `make install` but you can install manually by running `make create-and-install-man-file`.
|
||||||
|
|
||||||
|
### Uninstallation
|
||||||
|
|
||||||
|
To uninstall ResgenSwift: `make uninstall`.
|
||||||
|
21
SampleFiles/Colors/Generated/ColorYolo+GenAllScript.swift
Normal file
21
SampleFiles/Colors/Generated/ColorYolo+GenAllScript.swift
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Generated by ResgenSwift.Color 1.2
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
extension ColorYolo {
|
||||||
|
|
||||||
|
/// Color red is #FF0000 (light) or #FF0000 (dark)"
|
||||||
|
var red: Color {
|
||||||
|
Color("red")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Color green_alpha_50 is #A000FF00 (light) or #A000FF00 (dark)"
|
||||||
|
var green_alpha_50: Color {
|
||||||
|
Color("green_alpha_50")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Color blue_light_dark is #0000FF (light) or #0000AA (dark)"
|
||||||
|
var blue_light_dark: Color {
|
||||||
|
Color("blue_light_dark")
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +0,0 @@
|
|||||||
// 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")!
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
// Generated from ColorToolCore at 2022-02-14 09:30:19 +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")!
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
// 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")!
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
// Generated by ResgenSwift.ColorTool 1.0.0
|
|
||||||
|
|
||||||
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")!
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,8 @@
|
|||||||
// Generated from ColorToolCore at 2021-12-20 15:34:55 +0000
|
// Generated by ResgenSwift.Color 1.2
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
extension R2Color {
|
extension UIColorYolo {
|
||||||
|
|
||||||
/// Color red is #FF0000 (light) or #FF0000 (dark)"
|
/// Color red is #FF0000 (light) or #FF0000 (dark)"
|
||||||
@objc var red: UIColor {
|
@objc var red: UIColor {
|
||||||
@ -14,8 +14,8 @@ extension R2Color {
|
|||||||
UIColor(named: "green_alpha_50")!
|
UIColor(named: "green_alpha_50")!
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Color blue_light_dark is #0000FF (light) or #0000FF (dark)"
|
/// Color blue_light_dark is #0000FF (light) or #0000AA (dark)"
|
||||||
@objc var blue_light_dark: UIColor {
|
@objc var blue_light_dark: UIColor {
|
||||||
UIColor(named: "blue_light_dark")!
|
UIColor(named: "blue_light_dark")!
|
||||||
}
|
}
|
||||||
}
|
}
|
61
SampleFiles/Fonts/Generated/FontYolo+GenAllScript.swift
Normal file
61
SampleFiles/Fonts/Generated/FontYolo+GenAllScript.swift
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Generated by ResgenSwift.Fonts 1.2
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
extension FontYolo {
|
||||||
|
|
||||||
|
enum FontName: String {
|
||||||
|
case LatoItalic = "Lato-Italic"
|
||||||
|
case LatoLightItalic = "Lato-LightItalic"
|
||||||
|
case LatoHairline = "Lato-Hairline"
|
||||||
|
case LatoBold = "Lato-Bold"
|
||||||
|
case LatoBlack = "Lato-Black"
|
||||||
|
case LatoRegular = "Lato-Regular"
|
||||||
|
case LatoBlackItalic = "Lato-BlackItalic"
|
||||||
|
case LatoBoldItalic = "Lato-BoldItalic"
|
||||||
|
case LatoLight = "Lato-Light"
|
||||||
|
case LatoHairlineItalic = "Lato-HairlineItalic"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Getter
|
||||||
|
|
||||||
|
func LatoItalic(withSize size: CGFloat) -> Font {
|
||||||
|
Font.custom(FontName.LatoItalic.rawValue, size: size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoLightItalic(withSize size: CGFloat) -> Font {
|
||||||
|
Font.custom(FontName.LatoLightItalic.rawValue, size: size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoHairline(withSize size: CGFloat) -> Font {
|
||||||
|
Font.custom(FontName.LatoHairline.rawValue, size: size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoBold(withSize size: CGFloat) -> Font {
|
||||||
|
Font.custom(FontName.LatoBold.rawValue, size: size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoBlack(withSize size: CGFloat) -> Font {
|
||||||
|
Font.custom(FontName.LatoBlack.rawValue, size: size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoRegular(withSize size: CGFloat) -> Font {
|
||||||
|
Font.custom(FontName.LatoRegular.rawValue, size: size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoBlackItalic(withSize size: CGFloat) -> Font {
|
||||||
|
Font.custom(FontName.LatoBlackItalic.rawValue, size: size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoBoldItalic(withSize size: CGFloat) -> Font {
|
||||||
|
Font.custom(FontName.LatoBoldItalic.rawValue, size: size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoLight(withSize size: CGFloat) -> Font {
|
||||||
|
Font.custom(FontName.LatoLight.rawValue, size: size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoHairlineItalic(withSize size: CGFloat) -> Font {
|
||||||
|
Font.custom(FontName.LatoHairlineItalic.rawValue, size: size)
|
||||||
|
}
|
||||||
|
}
|
@ -1,62 +0,0 @@
|
|||||||
// Generated from FontToolCore
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension R2Font {
|
|
||||||
|
|
||||||
enum FontName: String {
|
|
||||||
case LatoItalic = "Lato-Italic"
|
|
||||||
case LatoLightItalic = "Lato-LightItalic"
|
|
||||||
case LatoHairline = "Lato-Hairline"
|
|
||||||
case LatoBold = "Lato-Bold"
|
|
||||||
case LatoBlack = "Lato-Black"
|
|
||||||
case LatoRegular = "Lato-Regular"
|
|
||||||
case LatoBlackItalic = "Lato-BlackItalic"
|
|
||||||
case LatoBoldItalic = "Lato-BoldItalic"
|
|
||||||
case LatoLight = "Lato-Light"
|
|
||||||
case LatoHairlineItalic = "Lato-HairlineItalic"
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Getter
|
|
||||||
|
|
||||||
func LatoItalic(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoItalic.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoLightItalic(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoLightItalic.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoHairline(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoHairline.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoBold(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoBold.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoBlack(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoBlack.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoRegular(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoRegular.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoBlackItalic(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoBlackItalic.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoBoldItalic(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoBoldItalic.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoLight(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoLight.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoHairlineItalic(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoHairlineItalic.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
// Generated from FontToolCore
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension R2Font {
|
|
||||||
|
|
||||||
enum FontName: String {
|
|
||||||
case LatoItalic = "Lato-Italic"
|
|
||||||
case LatoLightItalic = "Lato-LightItalic"
|
|
||||||
case LatoHairline = "Lato-Hairline"
|
|
||||||
case LatoBold = "Lato-Bold"
|
|
||||||
case LatoBlack = "Lato-Black"
|
|
||||||
case LatoRegular = "Lato-Regular"
|
|
||||||
case LatoBlackItalic = "Lato-BlackItalic"
|
|
||||||
case LatoBoldItalic = "Lato-BoldItalic"
|
|
||||||
case LatoLight = "Lato-Light"
|
|
||||||
case LatoHairlineItalic = "Lato-HairlineItalic"
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Getter
|
|
||||||
|
|
||||||
func LatoItalic(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoItalic.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoLightItalic(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoLightItalic.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoHairline(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoHairline.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoBold(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoBold.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoBlack(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoBlack.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoRegular(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoRegular.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoBlackItalic(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoBlackItalic.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoBoldItalic(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoBoldItalic.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoLight(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoLight.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
func LatoHairlineItalic(withSize size: CGFloat) -> UIFont {
|
|
||||||
UIFont(name: FontName.LatoHairlineItalic.rawValue, size: size)!
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
// Lato/Lato-Italic.ttf Lato/Lato-LightItalic.ttf Lato/Lato-Thin.ttf Lato/Lato-Bold.ttf Lato/Lato-Black.ttf Lato/Lato-Regular.ttf Lato/Lato-BlackItalic.ttf Lato/Lato-BoldItalic.ttf Lato/Lato-Light.ttf Lato/Lato-ThinItalic.ttf
|
|
||||||
// Generated from FontToolCore
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension UIFont {
|
|
||||||
|
|
||||||
enum FontName: String {
|
|
||||||
case LatoItalic = "Lato-Italic"
|
|
||||||
case LatoLightItalic = "Lato-LightItalic"
|
|
||||||
case LatoHairline = "Lato-Hairline"
|
|
||||||
case LatoBold = "Lato-Bold"
|
|
||||||
case LatoBlack = "Lato-Black"
|
|
||||||
case LatoRegular = "Lato-Regular"
|
|
||||||
case LatoBlackItalic = "Lato-BlackItalic"
|
|
||||||
case LatoBoldItalic = "Lato-BoldItalic"
|
|
||||||
case LatoLight = "Lato-Light"
|
|
||||||
case LatoHairlineItalic = "Lato-HairlineItalic"
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Getter
|
|
||||||
|
|
||||||
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 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 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 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 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)!
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
// Generated from FontToolCore
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension UIFont {
|
|
||||||
|
|
||||||
enum FontName: String {
|
|
||||||
case LatoItalic = "Lato-Italic"
|
|
||||||
case LatoLightItalic = "Lato-LightItalic"
|
|
||||||
case LatoHairline = "Lato-Hairline"
|
|
||||||
case LatoBold = "Lato-Bold"
|
|
||||||
case LatoBlack = "Lato-Black"
|
|
||||||
case LatoRegular = "Lato-Regular"
|
|
||||||
case LatoBlackItalic = "Lato-BlackItalic"
|
|
||||||
case LatoBoldItalic = "Lato-BoldItalic"
|
|
||||||
case LatoLight = "Lato-Light"
|
|
||||||
case LatoHairlineItalic = "Lato-HairlineItalic"
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Getter
|
|
||||||
|
|
||||||
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 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 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 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 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)!
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
// Generated by ResgenSwift.FontTool 1.0.0
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension UIFont {
|
|
||||||
|
|
||||||
enum FontName: String {
|
|
||||||
case LatoItalic = "Lato-Italic"
|
|
||||||
case LatoLightItalic = "Lato-LightItalic"
|
|
||||||
case LatoHairline = "Lato-Hairline"
|
|
||||||
case LatoBold = "Lato-Bold"
|
|
||||||
case LatoBlack = "Lato-Black"
|
|
||||||
case LatoRegular = "Lato-Regular"
|
|
||||||
case LatoBlackItalic = "Lato-BlackItalic"
|
|
||||||
case LatoBoldItalic = "Lato-BoldItalic"
|
|
||||||
case LatoLight = "Lato-Light"
|
|
||||||
case LatoHairlineItalic = "Lato-HairlineItalic"
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Getter
|
|
||||||
|
|
||||||
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 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 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 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 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)!
|
|
||||||
}
|
|
||||||
}
|
|
61
SampleFiles/Fonts/Generated/UIFontYolo+GenAllScript.swift
Normal file
61
SampleFiles/Fonts/Generated/UIFontYolo+GenAllScript.swift
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Generated by ResgenSwift.Fonts 1.2
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIFontYolo {
|
||||||
|
|
||||||
|
enum FontName: String {
|
||||||
|
case LatoItalic = "Lato-Italic"
|
||||||
|
case LatoLightItalic = "Lato-LightItalic"
|
||||||
|
case LatoHairline = "Lato-Hairline"
|
||||||
|
case LatoBold = "Lato-Bold"
|
||||||
|
case LatoBlack = "Lato-Black"
|
||||||
|
case LatoRegular = "Lato-Regular"
|
||||||
|
case LatoBlackItalic = "Lato-BlackItalic"
|
||||||
|
case LatoBoldItalic = "Lato-BoldItalic"
|
||||||
|
case LatoLight = "Lato-Light"
|
||||||
|
case LatoHairlineItalic = "Lato-HairlineItalic"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Getter
|
||||||
|
|
||||||
|
func LatoItalic(withSize size: CGFloat) -> UIFont {
|
||||||
|
UIFont(name: FontName.LatoItalic.rawValue, size: size)!
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoLightItalic(withSize size: CGFloat) -> UIFont {
|
||||||
|
UIFont(name: FontName.LatoLightItalic.rawValue, size: size)!
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoHairline(withSize size: CGFloat) -> UIFont {
|
||||||
|
UIFont(name: FontName.LatoHairline.rawValue, size: size)!
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoBold(withSize size: CGFloat) -> UIFont {
|
||||||
|
UIFont(name: FontName.LatoBold.rawValue, size: size)!
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoBlack(withSize size: CGFloat) -> UIFont {
|
||||||
|
UIFont(name: FontName.LatoBlack.rawValue, size: size)!
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoRegular(withSize size: CGFloat) -> UIFont {
|
||||||
|
UIFont(name: FontName.LatoRegular.rawValue, size: size)!
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoBlackItalic(withSize size: CGFloat) -> UIFont {
|
||||||
|
UIFont(name: FontName.LatoBlackItalic.rawValue, size: size)!
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoBoldItalic(withSize size: CGFloat) -> UIFont {
|
||||||
|
UIFont(name: FontName.LatoBoldItalic.rawValue, size: size)!
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoLight(withSize size: CGFloat) -> UIFont {
|
||||||
|
UIFont(name: FontName.LatoLight.rawValue, size: size)!
|
||||||
|
}
|
||||||
|
|
||||||
|
func LatoHairlineItalic(withSize size: CGFloat) -> UIFont {
|
||||||
|
UIFont(name: FontName.LatoHairlineItalic.rawValue, size: size)!
|
||||||
|
}
|
||||||
|
}
|
@ -1,62 +0,0 @@
|
|||||||
// Generated from FontToolCore
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension UIFont {
|
|
||||||
|
|
||||||
enum FontName: String {
|
|
||||||
case LatoItalic = "Lato-Italic"
|
|
||||||
case LatoLightItalic = "Lato-LightItalic"
|
|
||||||
case LatoHairline = "Lato-Hairline"
|
|
||||||
case LatoBold = "Lato-Bold"
|
|
||||||
case LatoBlack = "Lato-Black"
|
|
||||||
case LatoRegular = "Lato-Regular"
|
|
||||||
case LatoBlackItalic = "Lato-BlackItalic"
|
|
||||||
case LatoBoldItalic = "Lato-BoldItalic"
|
|
||||||
case LatoLight = "Lato-Light"
|
|
||||||
case LatoHairlineItalic = "Lato-HairlineItalic"
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Getter
|
|
||||||
|
|
||||||
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 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 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 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 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)!
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
21
SampleFiles/Fonts/Generated/test.plist
Normal file
21
SampleFiles/Fonts/Generated/test.plist
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NewArr</key>
|
||||||
|
<array/>
|
||||||
|
<key>UIAppFonts</key>
|
||||||
|
<array>
|
||||||
|
<string>Lato-Italic</string>
|
||||||
|
<string>Lato-LightItalic</string>
|
||||||
|
<string>Lato-Hairline</string>
|
||||||
|
<string>Lato-Bold</string>
|
||||||
|
<string>Lato-Black</string>
|
||||||
|
<string>Lato-Regular</string>
|
||||||
|
<string>Lato-BlackItalic</string>
|
||||||
|
<string>Lato-BoldItalic</string>
|
||||||
|
<string>Lato-Light</string>
|
||||||
|
<string>Lato-HairlineItalic</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
21
SampleFiles/Fonts/Generated/test2.plist
Normal file
21
SampleFiles/Fonts/Generated/test2.plist
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NewArr</key>
|
||||||
|
<array/>
|
||||||
|
<key>UIAppFonts</key>
|
||||||
|
<array>
|
||||||
|
<string>Lato-Italic</string>
|
||||||
|
<string>Lato-LightItalic</string>
|
||||||
|
<string>Lato-Hairline</string>
|
||||||
|
<string>Lato-Bold</string>
|
||||||
|
<string>Lato-Black</string>
|
||||||
|
<string>Lato-Regular</string>
|
||||||
|
<string>Lato-BlackItalic</string>
|
||||||
|
<string>Lato-BoldItalic</string>
|
||||||
|
<string>Lato-Light</string>
|
||||||
|
<string>Lato-HairlineItalic</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
31
SampleFiles/Images/Generated/ImageYolo+GenAllScript.swift
Normal file
31
SampleFiles/Images/Generated/ImageYolo+GenAllScript.swift
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Generated by ResgenSwift.Images 1.2
|
||||||
|
// Images from sampleImages
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
extension ImageYolo {
|
||||||
|
|
||||||
|
var article_notification_pull_detail: Image {
|
||||||
|
Image("article_notification_pull_detail")
|
||||||
|
}
|
||||||
|
|
||||||
|
var article_notification_pull: Image {
|
||||||
|
Image("article_notification_pull")
|
||||||
|
}
|
||||||
|
|
||||||
|
var new_article: Image {
|
||||||
|
Image("new_article")
|
||||||
|
}
|
||||||
|
|
||||||
|
var welcome_background: Image {
|
||||||
|
Image("welcome_background")
|
||||||
|
}
|
||||||
|
|
||||||
|
var article_trash: Image {
|
||||||
|
Image("article_trash")
|
||||||
|
}
|
||||||
|
|
||||||
|
var ic_close_article: Image {
|
||||||
|
Image("ic_close_article")
|
||||||
|
}
|
||||||
|
}
|
@ -1,32 +1,31 @@
|
|||||||
// Generated by ResgenSwift.Imagium 1.0.0
|
// Generated by ResgenSwift.Images 1.2
|
||||||
// Images from sampleImages
|
// Images from sampleImages
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
extension UIImage {
|
extension UIImage {
|
||||||
|
|
||||||
static var article_notification_pull_detail: UIImage {
|
var article_notification_pull_detail: UIImage {
|
||||||
UIImage(named: "article_notification_pull_detail")!
|
UIImage(named: "article_notification_pull_detail")!
|
||||||
}
|
}
|
||||||
|
|
||||||
static var article_notification_pull: UIImage {
|
var article_notification_pull: UIImage {
|
||||||
UIImage(named: "article_notification_pull")!
|
UIImage(named: "article_notification_pull")!
|
||||||
}
|
}
|
||||||
|
|
||||||
static var new_article: UIImage {
|
var new_article: UIImage {
|
||||||
UIImage(named: "new_article")!
|
UIImage(named: "new_article")!
|
||||||
}
|
}
|
||||||
|
|
||||||
static var welcome_background: UIImage {
|
var welcome_background: UIImage {
|
||||||
UIImage(named: "welcome_background")!
|
UIImage(named: "welcome_background")!
|
||||||
}
|
}
|
||||||
|
|
||||||
static var article_trash: UIImage {
|
var article_trash: UIImage {
|
||||||
UIImage(named: "article_trash")!
|
UIImage(named: "article_trash")!
|
||||||
}
|
}
|
||||||
|
|
||||||
static var ic_close_article: UIImage {
|
var ic_close_article: UIImage {
|
||||||
UIImage(named: "ic_close_article")!
|
UIImage(named: "ic_close_article")!
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
// Generated from Imagium at 2022-02-14 09:30:23 +0000
|
|
||||||
// Images from sampleImages
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension UIImage {
|
|
||||||
|
|
||||||
static var article_notification_pull_detail: UIImage {
|
|
||||||
UIImage(named: "article_notification_pull_detail")!
|
|
||||||
}
|
|
||||||
|
|
||||||
static var article_notification_pull: UIImage {
|
|
||||||
UIImage(named: "article_notification_pull")!
|
|
||||||
}
|
|
||||||
|
|
||||||
static var new_article: UIImage {
|
|
||||||
UIImage(named: "new_article")!
|
|
||||||
}
|
|
||||||
|
|
||||||
static var welcome_background: UIImage {
|
|
||||||
UIImage(named: "welcome_background")!
|
|
||||||
}
|
|
||||||
|
|
||||||
static var article_trash: UIImage {
|
|
||||||
UIImage(named: "article_trash")!
|
|
||||||
}
|
|
||||||
|
|
||||||
static var ic_close_article: UIImage {
|
|
||||||
UIImage(named: "ic_close_article")!
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
// Generated from StringToolCore at 2022-01-10 08:27:11 +0000
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
fileprivate let kStringsFileName = "sampleStrings"
|
|
||||||
|
|
||||||
extension MyString {
|
|
||||||
|
|
||||||
// MARK: - Webservice
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// en
|
|
||||||
var param_lang: String {
|
|
||||||
NSLocalizedString("param_lang", tableName: kStringsFileName, bundle: Bundle.main, value: "en", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Generic
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Back
|
|
||||||
var generic_back: String {
|
|
||||||
NSLocalizedString("generic_back", tableName: kStringsFileName, bundle: Bundle.main, value: "Back", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Loading data...
|
|
||||||
var generic_loading_data: String {
|
|
||||||
NSLocalizedString("generic_loading_data", tableName: kStringsFileName, bundle: Bundle.main, value: "Loading data...", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Welcome %@ !
|
|
||||||
var generic_welcome_firstname_format: String {
|
|
||||||
NSLocalizedString("generic_welcome_firstname_format", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome %@ !", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
// Generated by ResgenSwift.Strings.Stringium 1.0.0
|
// Generated by ResgenSwift.Strings.Stringium 1.2
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
@ -6,60 +6,68 @@ fileprivate let kStringsFileName = "sampleStrings"
|
|||||||
|
|
||||||
extension String {
|
extension String {
|
||||||
|
|
||||||
// MARK: - Webservice
|
enum Key: String {
|
||||||
|
case param_lang = "param_lang"
|
||||||
|
case generic_back = "generic_back"
|
||||||
|
case generic_loading_data = "generic_loading_data"
|
||||||
|
case generic_welcome_firstname_format = "generic_welcome_firstname_format"
|
||||||
|
case test_equal_symbol = "test_equal_symbol"
|
||||||
|
case placeholders_test_one = "placeholders_test_one"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Webservice
|
||||||
|
|
||||||
/// Translation in en :
|
/// Translation in en :
|
||||||
/// en
|
/// en
|
||||||
static var param_lang: String {
|
var param_lang: String {
|
||||||
NSLocalizedString("param_lang", tableName: kStringsFileName, bundle: Bundle.main, value: "en", comment: "")
|
NSLocalizedString("param_lang", tableName: kStringsFileName, bundle: Bundle.main, value: "en", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Generic
|
// MARK: - Generic
|
||||||
|
|
||||||
/// Translation in en :
|
/// Translation in en :
|
||||||
/// Back
|
/// Back
|
||||||
static var generic_back: String {
|
var generic_back: String {
|
||||||
NSLocalizedString("generic_back", tableName: kStringsFileName, bundle: Bundle.main, value: "Back", comment: "")
|
NSLocalizedString("generic_back", tableName: kStringsFileName, bundle: Bundle.main, value: "Back", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translation in en :
|
/// Translation in en :
|
||||||
/// Loading data...
|
/// Loading data...
|
||||||
static var generic_loading_data: String {
|
var generic_loading_data: String {
|
||||||
NSLocalizedString("generic_loading_data", tableName: kStringsFileName, bundle: Bundle.main, value: "Loading data...", comment: "")
|
NSLocalizedString("generic_loading_data", tableName: kStringsFileName, bundle: Bundle.main, value: "Loading data...", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translation in en :
|
/// Translation in en :
|
||||||
/// Welcome \"%@\" !
|
/// Welcome \"%@\" !
|
||||||
static var generic_welcome_firstname_format: String {
|
var generic_welcome_firstname_format: String {
|
||||||
NSLocalizedString("generic_welcome_firstname_format", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" !", comment: "")
|
NSLocalizedString("generic_welcome_firstname_format", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" !", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translation in en :
|
/// Translation in en :
|
||||||
/// Welcome \"%@\" !
|
/// Welcome \"%@\" !
|
||||||
static func generic_welcome_firstname_format(arg0: String) -> String {
|
func generic_welcome_firstname_format(arg0: String) -> String {
|
||||||
String(format: Self.generic_welcome_firstname_format, arg0)
|
String(format: self.generic_welcome_firstname_format, arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - EqualSymbol
|
// MARK: - EqualSymbol
|
||||||
|
|
||||||
/// Translation in en :
|
/// Translation in en :
|
||||||
/// 1€ = 1 point !
|
/// 1€ = 1 point !
|
||||||
static var test_equal_symbol: String {
|
var test_equal_symbol: String {
|
||||||
NSLocalizedString("test_equal_symbol", tableName: kStringsFileName, bundle: Bundle.main, value: "1€ = 1 point !", comment: "")
|
NSLocalizedString("test_equal_symbol", tableName: kStringsFileName, bundle: Bundle.main, value: "1€ = 1 point !", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Placeholders
|
// MARK: - Placeholders
|
||||||
|
|
||||||
/// Translation in en :
|
/// Translation in en :
|
||||||
/// You %%: %2$@ %1$@ Age: %3$d
|
/// You %%: %2$@ %1$@ Age: %3$d
|
||||||
static var placeholders_test_one: String {
|
var placeholders_test_one: String {
|
||||||
NSLocalizedString("placeholders_test_one", tableName: kStringsFileName, bundle: Bundle.main, value: "You %%: %2$@ %1$@ Age: %3$d", comment: "")
|
NSLocalizedString("placeholders_test_one", tableName: kStringsFileName, bundle: Bundle.main, value: "You %%: %2$@ %1$@ Age: %3$d", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translation in en :
|
/// Translation in en :
|
||||||
/// You %%: %2$@ %1$@ Age: %3$d
|
/// You %%: %2$@ %1$@ Age: %3$d
|
||||||
static func placeholders_test_one(arg0: String, arg1: String, arg2: Int) -> String {
|
func placeholders_test_one(arg0: String, arg1: String, arg2: Int) -> String {
|
||||||
String(format: Self.placeholders_test_one, arg0, arg1, arg2)
|
String(format: self.placeholders_test_one, arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
// Generated from Strings-Stringium at 2022-03-07 11:02:15 +0000
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
fileprivate let kStringsFileName = "sampleStrings"
|
|
||||||
|
|
||||||
extension String {
|
|
||||||
|
|
||||||
// MARK: - Webservice
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// en
|
|
||||||
static var param_lang: String {
|
|
||||||
NSLocalizedString("param_lang", tableName: kStringsFileName, bundle: Bundle.main, value: "en", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Generic
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Back
|
|
||||||
static var generic_back: String {
|
|
||||||
NSLocalizedString("generic_back", tableName: kStringsFileName, bundle: Bundle.main, value: "Back", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Loading data...
|
|
||||||
static var generic_loading_data: String {
|
|
||||||
NSLocalizedString("generic_loading_data", tableName: kStringsFileName, bundle: Bundle.main, value: "Loading data...", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Welcome \"%@\" !
|
|
||||||
static var generic_welcome_firstname_format: String {
|
|
||||||
NSLocalizedString("generic_welcome_firstname_format", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" !", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Welcome \"%@\" !
|
|
||||||
static func generic_welcome_firstname_format(arg0: String) -> String {
|
|
||||||
String(format: Self.generic_welcome_firstname_format, arg0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Placeholders
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// You %%: %2$@ %1$@ Age: %3$d
|
|
||||||
static var placeholders_test_one: String {
|
|
||||||
NSLocalizedString("placeholders_test_one", tableName: kStringsFileName, bundle: Bundle.main, value: "You %%: %2$@ %1$@ Age: %3$d", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// You %%: %2$@ %1$@ Age: %3$d
|
|
||||||
static func placeholders_test_one(arg0: String, arg1: String, arg2: Int) -> String {
|
|
||||||
String(format: Self.placeholders_test_one, arg0, arg1, arg2)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
// Generated from StringToolCore at 2022-01-10 08:39:52 +0000
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
fileprivate let kStringsFileName = "sampleStrings"
|
|
||||||
|
|
||||||
extension String {
|
|
||||||
|
|
||||||
// MARK: - Webservice
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// en
|
|
||||||
static var param_lang: String {
|
|
||||||
NSLocalizedString("param_lang", tableName: kStringsFileName, bundle: Bundle.main, value: "en", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Generic
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Back
|
|
||||||
static var generic_back: String {
|
|
||||||
NSLocalizedString("generic_back", tableName: kStringsFileName, bundle: Bundle.main, value: "Back", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Loading data...
|
|
||||||
static var generic_loading_data: String {
|
|
||||||
NSLocalizedString("generic_loading_data", tableName: kStringsFileName, bundle: Bundle.main, value: "Loading data...", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Welcome \"%@\" !
|
|
||||||
static var generic_welcome_firstname_format: String {
|
|
||||||
NSLocalizedString("generic_welcome_firstname_format", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" !", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
// Generated from Strings-Stringium at 2022-03-07 11:00:52 +0000
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
fileprivate let kStringsFileName = "sampleStrings"
|
|
||||||
|
|
||||||
extension StringTest {
|
|
||||||
|
|
||||||
// MARK: - Webservice
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// en
|
|
||||||
var param_lang: String {
|
|
||||||
NSLocalizedString("param_lang", tableName: kStringsFileName, bundle: Bundle.main, value: "en", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Generic
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Back
|
|
||||||
var generic_back: String {
|
|
||||||
NSLocalizedString("generic_back", tableName: kStringsFileName, bundle: Bundle.main, value: "Back", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Loading data...
|
|
||||||
var generic_loading_data: String {
|
|
||||||
NSLocalizedString("generic_loading_data", tableName: kStringsFileName, bundle: Bundle.main, value: "Loading data...", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Welcome \"%@\" !
|
|
||||||
var generic_welcome_firstname_format: String {
|
|
||||||
NSLocalizedString("generic_welcome_firstname_format", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" !", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// Welcome \"%@\" !
|
|
||||||
func generic_welcome_firstname_format(arg0: String) -> String {
|
|
||||||
String(format: self.generic_welcome_firstname_format, arg0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Placeholders
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// You %%: %2$@ %1$@ Age: %3$d
|
|
||||||
var placeholders_test_one: String {
|
|
||||||
NSLocalizedString("placeholders_test_one", tableName: kStringsFileName, bundle: Bundle.main, value: "You %%: %2$@ %1$@ Age: %3$d", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in en :
|
|
||||||
/// You %%: %2$@ %1$@ Age: %3$d
|
|
||||||
func placeholders_test_one(arg0: String, arg1: String, arg2: Int) -> String {
|
|
||||||
String(format: self.placeholders_test_one, arg0, arg1, arg2)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Apple Strings File
|
* Apple Strings File
|
||||||
* Generated by ResgenSwift 1.0.0
|
* Generated by ResgenSwift 1.2
|
||||||
* Language: en-us
|
* Language: en-us
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Apple Strings File
|
* Apple Strings File
|
||||||
* Generated by ResgenSwift 1.0.0
|
* Generated by ResgenSwift 1.2
|
||||||
* Language: en
|
* Language: en
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Apple Strings File
|
* Apple Strings File
|
||||||
* Generated by ResgenSwift 1.0.0
|
* Generated by ResgenSwift 1.2
|
||||||
* Language: fr
|
* Language: fr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,23 +1,20 @@
|
|||||||
// Generated by ResgenSwift.Strings.Tags 1.0.0
|
// Generated by ResgenSwift.Strings.Tags 1.2
|
||||||
|
|
||||||
// typelias Tags = String
|
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
extension Tags {
|
extension Tags {
|
||||||
|
|
||||||
// MARK: - ScreenTag
|
// MARK: - ScreenTag
|
||||||
|
|
||||||
/// Translation in ium :
|
/// Translation in ium :
|
||||||
/// Ecran un
|
/// Ecran un
|
||||||
static var screen_one: String {
|
var screen_one: String {
|
||||||
"Ecran un"
|
"Ecran un"
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translation in ium :
|
/// Translation in ium :
|
||||||
/// Ecran deux
|
/// Ecran deux
|
||||||
static var screen_two: String {
|
var screen_two: String {
|
||||||
"Ecran deux"
|
"Ecran deux"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// Generated from Strings-Tags at 2022-02-14 09:30:20 +0000
|
|
||||||
|
|
||||||
// typelias Tags = String
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension Tags {
|
|
||||||
|
|
||||||
// MARK: - ScreenTag
|
|
||||||
|
|
||||||
/// Translation in ium :
|
|
||||||
/// Ecran un
|
|
||||||
static var screen_one: String {
|
|
||||||
"Ecran un"
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translation in ium :
|
|
||||||
/// Ecran deux
|
|
||||||
static var screen_two: String {
|
|
||||||
"Ecran deux"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -3,25 +3,28 @@
|
|||||||
FORCE_FLAG="$1"
|
FORCE_FLAG="$1"
|
||||||
|
|
||||||
# Font
|
# Font
|
||||||
swift run -c release FontTool $FORCE_FLAG "./Fonts/sampleFontsAll.txt" \
|
swift run -c release ResgenSwift fonts $FORCE_FLAG "./Fonts/sampleFontsAll.txt" \
|
||||||
--extension-output-path "./Fonts/Generated" \
|
--extension-output-path "./Fonts/Generated" \
|
||||||
--extension-name "UIFont" \
|
--extension-name "UIFontYolo" \
|
||||||
--extension-suffix "GenAllScript"
|
--extension-name-swift-ui "FontYolo" \
|
||||||
|
--extension-suffix "GenAllScript" \
|
||||||
|
--info-plist-paths "./Fonts/Generated/test.plist ./Fonts/Generated/test2.plist"
|
||||||
|
|
||||||
echo "\n-------------------------\n"
|
echo "\n-------------------------\n"
|
||||||
|
|
||||||
# Color
|
# Color
|
||||||
swift run -c release ColorTool $FORCE_FLAG "./Colors/sampleColors1.txt" \
|
swift run -c release ResgenSwift colors $FORCE_FLAG "./Colors/sampleColors1.txt" \
|
||||||
--style all \
|
--style all \
|
||||||
--xcassets-path "./Colors/colors.xcassets" \
|
--xcassets-path "./Colors/colors.xcassets" \
|
||||||
--extension-output-path "./Colors/Generated/" \
|
--extension-output-path "./Colors/Generated/" \
|
||||||
--extension-name "UIColor" \
|
--extension-name "UIColorYolo" \
|
||||||
|
--extension-name-swift-ui "ColorYolo" \
|
||||||
--extension-suffix "GenAllScript"
|
--extension-suffix "GenAllScript"
|
||||||
|
|
||||||
echo "\n-------------------------\n"
|
echo "\n-------------------------\n"
|
||||||
|
|
||||||
# Twine
|
# Twine
|
||||||
swift run -c release Strings twine $FORCE_FLAG "./Twine/sampleStrings.txt" \
|
swift run -c release ResgenSwift strings twine $FORCE_FLAG "./Twine/sampleStrings.txt" \
|
||||||
--output-path "./Twine/Generated" \
|
--output-path "./Twine/Generated" \
|
||||||
--langs "fr en en-us" \
|
--langs "fr en en-us" \
|
||||||
--default-lang "en" \
|
--default-lang "en" \
|
||||||
@ -30,7 +33,7 @@ swift run -c release Strings twine $FORCE_FLAG "./Twine/sampleStrings.txt" \
|
|||||||
echo "\n-------------------------\n"
|
echo "\n-------------------------\n"
|
||||||
|
|
||||||
# Strings
|
# Strings
|
||||||
swift run -c release Strings stringium $FORCE_FLAG "./Strings/sampleStrings.txt" \
|
swift run -c release ResgenSwift strings stringium $FORCE_FLAG "./Strings/sampleStrings.txt" \
|
||||||
--output-path "./Strings/Generated" \
|
--output-path "./Strings/Generated" \
|
||||||
--langs "fr en en-us" \
|
--langs "fr en en-us" \
|
||||||
--default-lang "en" \
|
--default-lang "en" \
|
||||||
@ -41,7 +44,7 @@ swift run -c release Strings stringium $FORCE_FLAG "./Strings/sampleStrings.txt"
|
|||||||
echo "\n-------------------------\n"
|
echo "\n-------------------------\n"
|
||||||
|
|
||||||
# Tags
|
# Tags
|
||||||
swift run -c release Strings tags $FORCE_FLAG "./Tags/sampleTags.txt" \
|
swift run -c release ResgenSwift strings tags $FORCE_FLAG "./Tags/sampleTags.txt" \
|
||||||
--lang "ium" \
|
--lang "ium" \
|
||||||
--extension-output-path "./Tags/Generated" \
|
--extension-output-path "./Tags/Generated" \
|
||||||
--extension-name "Tags" \
|
--extension-name "Tags" \
|
||||||
@ -50,8 +53,9 @@ swift run -c release Strings tags $FORCE_FLAG "./Tags/sampleTags.txt" \
|
|||||||
echo "\n-------------------------\n"
|
echo "\n-------------------------\n"
|
||||||
|
|
||||||
# Images
|
# Images
|
||||||
swift run -c release Imagium $FORCE_FLAG "./Images/sampleImages.txt" \
|
swift run -c release ResgenSwift images $FORCE_FLAG "./Images/sampleImages.txt" \
|
||||||
--xcassets-path "./Images/imagium.xcassets" \
|
--xcassets-path "./Images/imagium.xcassets" \
|
||||||
--extension-output-path "./Images/Generated" \
|
--extension-output-path "./Images/Generated" \
|
||||||
--extension-name "UIImage" \
|
--extension-name "UIImage" \
|
||||||
|
--extension-name-swift-ui "ImageYolo" \
|
||||||
--extension-suffix "GenAllScript"
|
--extension-suffix "GenAllScript"
|
||||||
|
91
SampleFiles/resgenConfiguration.yml
Normal file
91
SampleFiles/resgenConfiguration.yml
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
---
|
||||||
|
#
|
||||||
|
# Class architecture
|
||||||
|
#
|
||||||
|
architecture:
|
||||||
|
property: R
|
||||||
|
classname: R
|
||||||
|
path: ./Tags
|
||||||
|
children:
|
||||||
|
- property: images
|
||||||
|
classname: R2Image
|
||||||
|
- property: strings
|
||||||
|
classname: R2String
|
||||||
|
- property: fonts
|
||||||
|
classname: R2Font
|
||||||
|
- property: images
|
||||||
|
classname: R2Image
|
||||||
|
- property: ui
|
||||||
|
classname: R2UI
|
||||||
|
children:
|
||||||
|
- property: images
|
||||||
|
classname: R2UIImage
|
||||||
|
- property: fonts
|
||||||
|
classname: R2UIFont
|
||||||
|
- property: images
|
||||||
|
classname: R2UIImage
|
||||||
|
|
||||||
|
#
|
||||||
|
# Strings
|
||||||
|
#
|
||||||
|
strings:
|
||||||
|
-
|
||||||
|
inputFile: ./Strings/sampleStrings.txt
|
||||||
|
outputPath: ./Strings/Generated
|
||||||
|
langs: "fr en en-us"
|
||||||
|
defaultLang: en
|
||||||
|
extensionOutputPath: ./Strings/Generated
|
||||||
|
extensionName: String
|
||||||
|
extensionSuffix: GenAllScript
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Images
|
||||||
|
#
|
||||||
|
images:
|
||||||
|
-
|
||||||
|
inputFile: ./Images/sampleImages.txt
|
||||||
|
xcassetsPath: ./Images/imagium.xcassets
|
||||||
|
extensionOutputPath: ./Images/Generated
|
||||||
|
extensionName: UIImage
|
||||||
|
extensionNameSwiftUI: ImageYolo
|
||||||
|
extensionSuffix: GenAllScript
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Colors
|
||||||
|
#
|
||||||
|
colors:
|
||||||
|
-
|
||||||
|
inputFile: ./Colors/sampleColors1.txt
|
||||||
|
style: all
|
||||||
|
xcassetsPath: ./Colors/colors.xcassets
|
||||||
|
extensionOutputPath: ./Colors/Generated/
|
||||||
|
extensionName: UIColorYolo
|
||||||
|
extensionNameSwiftUI: ColorYolo
|
||||||
|
extensionSuffix: GenAllScript
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tags
|
||||||
|
#
|
||||||
|
tags:
|
||||||
|
-
|
||||||
|
inputFile: ./Tags/sampleTags.txt
|
||||||
|
lang: ium
|
||||||
|
extensionOutputPath: ./Tags/Generated
|
||||||
|
extensionName: Tags
|
||||||
|
extensionSuffix: GenAllScript
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Fonts
|
||||||
|
#
|
||||||
|
fonts:
|
||||||
|
-
|
||||||
|
inputFile: ./Fonts/sampleFontsAll.txt
|
||||||
|
extensionOutputPath: ./Fonts/Generated
|
||||||
|
extensionName: UIFontYolo
|
||||||
|
extensionNameSwiftUI: FontYolo
|
||||||
|
extensionSuffix: GenAllScript
|
||||||
|
infoPlistPaths: "./Fonts/Generated/test.plist ./Fonts/Generated/test2.plist"
|
@ -1,35 +0,0 @@
|
|||||||
//
|
|
||||||
// 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 "error:[ColorTool] Bad line format: \(info). Accepted format are: colorName=\"#RGB/#ARGB\"; colorName \"#RGB/#ARGB\"; colorName \"#RGB/#ARGB\" \"#RGB/#ARGB\""
|
|
||||||
|
|
||||||
case .writeAsset(let info):
|
|
||||||
return "error:[ColorTool] An error occured while writing color in Xcasset: \(info)"
|
|
||||||
|
|
||||||
case .writeExtension(let filename, let info):
|
|
||||||
return "error:[ColorTool] An error occured while writing extension in \(filename): \(info)"
|
|
||||||
|
|
||||||
case .fileNotExists(let filename):
|
|
||||||
return "error:[ColorTool] File \(filename) does not exists"
|
|
||||||
|
|
||||||
case .badColorDefinition(let lightColor, let darkColor):
|
|
||||||
return "error:[ColorTool]One of these two colors has invalid synthax: -\(lightColor)- or -\(darkColor)-"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
//
|
|
||||||
// ColorToolOptions.swift
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Created by Thibaut Schmitt on 17/01/2022.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import ArgumentParser
|
|
||||||
|
|
||||||
struct ColorToolOptions: ParsableArguments {
|
|
||||||
@Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation")
|
|
||||||
var forceGeneration = false
|
|
||||||
|
|
||||||
@Argument(help: "Input files where colors ared defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
|
||||||
var inputFile: String
|
|
||||||
|
|
||||||
@Option(help: "Color style to generate: light for light colors only, or all for dark and light colors")
|
|
||||||
fileprivate var style: String
|
|
||||||
|
|
||||||
@Option(help: "Path of xcassets where to generate colors", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
|
||||||
var xcassetsPath: String
|
|
||||||
|
|
||||||
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
|
||||||
var extensionOutputPath: String
|
|
||||||
|
|
||||||
@Option(help: "Extension name. If not specified, it will generate an UIColor extension. Using default extension name will generate static property.")
|
|
||||||
var extensionName: String = ColorTool.defaultExtensionName
|
|
||||||
|
|
||||||
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+ColorsMyApp.swift")
|
|
||||||
var extensionSuffix: String = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ColorToolOptions {
|
|
||||||
var colorStyle: ColorStyle {
|
|
||||||
ColorStyle(rawValue: style) ?? .all
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
//
|
|
||||||
// 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")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
//
|
|
||||||
// File.swift
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Created by Thibaut Schmitt on 29/08/2022.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
enum ColorStyle: String, Decodable {
|
|
||||||
case light
|
|
||||||
case all
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
//
|
|
||||||
// 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]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
//
|
|
||||||
// FontOptions.swift
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Created by Thibaut Schmitt on 17/01/2022.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import ArgumentParser
|
|
||||||
|
|
||||||
struct FontOptions: ParsableArguments {
|
|
||||||
@Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation")
|
|
||||||
var forceGeneration = false
|
|
||||||
|
|
||||||
@Argument(help: "Input files where fonts ared defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
|
||||||
var inputFile: String
|
|
||||||
|
|
||||||
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
|
||||||
var extensionOutputPath: String
|
|
||||||
|
|
||||||
@Option(help: "Extension name. If not specified, it will generate an UIFont extension. Using default extension name will generate static property.")
|
|
||||||
var extensionName: String = FontTool.defaultExtensionName
|
|
||||||
|
|
||||||
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+FontsMyApp.swift")
|
|
||||||
var extensionSuffix: String = ""
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
//
|
|
||||||
// FontToolError.swift
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Created by Thibaut Schmitt on 13/12/2021.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
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.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.toolName)] Input folder not found: \(inputFolder)"
|
|
||||||
|
|
||||||
case .fileNotExists(let filename):
|
|
||||||
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)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
//
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
//
|
|
||||||
// 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 {
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
//
|
|
||||||
// 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)!
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
//
|
|
||||||
// ImageExtensionGenerator.swift
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Created by Thibaut Schmitt on 14/02/2022.
|
|
||||||
//
|
|
||||||
|
|
||||||
import ToolCore
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
class ImageExtensionGenerator {
|
|
||||||
|
|
||||||
// MARK: - Extension files
|
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
// Create content
|
|
||||||
let extensionContent: String = {
|
|
||||||
var content = ""
|
|
||||||
images.forEach { img in
|
|
||||||
if staticVar {
|
|
||||||
content += "\n\(img.getStaticImageProperty())"
|
|
||||||
} else {
|
|
||||||
content += "\n\(img.getImageProperty())"
|
|
||||||
}
|
|
||||||
content += "\n "
|
|
||||||
}
|
|
||||||
return content
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Create file if not exists
|
|
||||||
let fileManager = FileManager()
|
|
||||||
if fileManager.fileExists(atPath: extensionFilePath) == false {
|
|
||||||
Shell.shell("touch", "\(extensionFilePath)")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate extension
|
|
||||||
Self.generateExtensionFile(extensionFilePath: extensionFilePath, extensionHeader, extensionContent, extensionFooter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - pragm
|
|
||||||
|
|
||||||
private static func generateExtensionFile(extensionFilePath: String, _ 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 = ImagiumError.writeFile(extensionFilePath, error.localizedDescription)
|
|
||||||
print(error.localizedDescription)
|
|
||||||
Imagium.exit(withError: error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func getHeader(inputFilename: String, extensionClassname: String) -> String {
|
|
||||||
"""
|
|
||||||
// Generated by ResgenSwift.Imagium \(ResgenSwiftVersion)
|
|
||||||
// Images from \(inputFilename)
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension \(extensionClassname) {
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func getFooter() -> String {
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//@objc var onboarding_foreground3: UIImage {
|
|
||||||
// return UIImage(named: "onboarding_foreground3")!
|
|
||||||
// }
|
|
@ -1,43 +0,0 @@
|
|||||||
//
|
|
||||||
// ImagiumError.swift
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Created by Thibaut Schmitt on 24/01/2022.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
enum ImagiumError: Error {
|
|
||||||
case inputFolderNotFound(String)
|
|
||||||
case fileNotExists(String)
|
|
||||||
case unknownImageExtension(String)
|
|
||||||
case getFileAttributed(String, String)
|
|
||||||
case rsvgConvertNotFound
|
|
||||||
case writeFile(String, String)
|
|
||||||
case unknown(String)
|
|
||||||
|
|
||||||
var localizedDescription: String {
|
|
||||||
switch self {
|
|
||||||
case .inputFolderNotFound(let inputFolder):
|
|
||||||
return " error:[\(Imagium.toolName)] Input folder not found: \(inputFolder)"
|
|
||||||
|
|
||||||
case .fileNotExists(let filename):
|
|
||||||
return " error:[\(Imagium.toolName)] File \(filename) does not exists"
|
|
||||||
|
|
||||||
case .unknownImageExtension(let filename):
|
|
||||||
return " error:[\(Imagium.toolName)] File \(filename) have an unhandled file extension. Cannot generate image."
|
|
||||||
|
|
||||||
case .getFileAttributed(let filename, let errorDescription):
|
|
||||||
return " error:[\(Imagium.toolName)] Getting file attributes of \(filename) failed with error: \(errorDescription)"
|
|
||||||
|
|
||||||
case .rsvgConvertNotFound:
|
|
||||||
return " error:[\(Imagium.toolName)] Can't find rsvg-convert (can be installed with 'brew remove imagemagick && brew install imagemagick --with-librsvg')"
|
|
||||||
|
|
||||||
case .writeFile(let subErrorDescription, let filename):
|
|
||||||
return " error:[\(Imagium.toolName)] An error occured while writing content to \(filename): \(subErrorDescription)"
|
|
||||||
|
|
||||||
case .unknown(let errorDescription):
|
|
||||||
return " error:[\(Imagium.toolName)] Unknown error: \(errorDescription)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
//
|
|
||||||
// ImagiumOptions.swift
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Created by Thibaut Schmitt on 24/01/2022.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import ArgumentParser
|
|
||||||
|
|
||||||
struct ImagiumOptions: ParsableArguments {
|
|
||||||
@Flag(name: .customShort("f"), help: "Should force script execution")
|
|
||||||
var forceExecution = false
|
|
||||||
|
|
||||||
@Flag(name: .customShort("F"), help: "Regenerate all images")
|
|
||||||
var forceExecutionAndGeneration = false
|
|
||||||
|
|
||||||
@Argument(help: "Input files where strings ared defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
|
||||||
var inputFile: String
|
|
||||||
|
|
||||||
@Option(help: "Xcassets path where to generate images.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
|
||||||
var xcassetsPath: String
|
|
||||||
|
|
||||||
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
|
||||||
var extensionOutputPath: String
|
|
||||||
|
|
||||||
@Option(help: "Extension name. If not specified, it will generate an UIImage extension. Using default extension name will generate static property.")
|
|
||||||
var extensionName: String = Imagium.defaultExtensionName
|
|
||||||
|
|
||||||
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+Image{extensionSuffix}.swift")
|
|
||||||
var extensionSuffix: String = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
swift run -c release Imagium $FORCE_FLAG "./Images/sampleImages.txt" \
|
|
||||||
--xcassets-path "./Images/imagium.xcassets" \
|
|
||||||
--extension-output-path "./Images/Generated" \
|
|
||||||
--extension-name "UIImage" \
|
|
||||||
--extension-suffix "GenAllScript"
|
|
||||||
*/
|
|
@ -9,7 +9,7 @@ import ToolCore
|
|||||||
import Foundation
|
import Foundation
|
||||||
import ArgumentParser
|
import ArgumentParser
|
||||||
|
|
||||||
struct ColorTool: ParsableCommand {
|
struct Colors: ParsableCommand {
|
||||||
|
|
||||||
// MARK: - CommandConfiguration
|
// MARK: - CommandConfiguration
|
||||||
|
|
||||||
@ -20,33 +20,20 @@ struct ColorTool: ParsableCommand {
|
|||||||
|
|
||||||
// MARK: - Static
|
// MARK: - Static
|
||||||
|
|
||||||
static let toolName = "ColorTool"
|
static let toolName = "Color"
|
||||||
static let defaultExtensionName = "UIColor"
|
static let defaultExtensionName = "UIColor"
|
||||||
|
static let defaultExtensionNameSUI = "Color"
|
||||||
static let assetsColorsFolderName = "Colors"
|
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
|
// MARK: - Command options
|
||||||
|
|
||||||
@OptionGroup var options: ColorToolOptions
|
@OptionGroup var options: ColorsToolOptions
|
||||||
|
|
||||||
// MARK: - Run
|
// MARK: - Run
|
||||||
|
|
||||||
public func run() throws {
|
public func run() throws {
|
||||||
print("[\(Self.toolName)] Starting colors generation")
|
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
|
// Check requirements
|
||||||
guard checkRequirements() else { return }
|
guard checkRequirements() else { return }
|
||||||
|
|
||||||
@ -54,20 +41,30 @@ struct ColorTool: ParsableCommand {
|
|||||||
|
|
||||||
// Delete current colors
|
// Delete current colors
|
||||||
deleteCurrentColors()
|
deleteCurrentColors()
|
||||||
|
|
||||||
// Get colors to generate
|
// Get colors to generate
|
||||||
let parsedColors = ColorFileParser.parse(options.inputFile,
|
let parsedColors = ColorFileParser.parse(options.inputFile,
|
||||||
colorStyle: options.colorStyle)
|
colorStyle: options.style)
|
||||||
|
// -> Time: 0.0020350217819213867 seconds
|
||||||
|
|
||||||
// Generate all colors in xcassets
|
// Generate all colors in xcassets
|
||||||
ColorXcassetHelper.generateXcassetColors(colors: parsedColors,
|
ColorXcassetHelper.generateXcassetColors(colors: parsedColors,
|
||||||
to: options.xcassetsPath)
|
to: options.xcassetsPath)
|
||||||
|
// -> Time: 3.4505380392074585 seconds
|
||||||
|
|
||||||
|
// Generate extension
|
||||||
|
ColorExtensionGenerator.writeExtensionFile(colors: parsedColors,
|
||||||
|
staticVar: options.staticMembers,
|
||||||
|
extensionName: options.extensionName,
|
||||||
|
extensionFilePath: options.extensionFilePath,
|
||||||
|
isSwiftUI: false)
|
||||||
|
|
||||||
// Generate extension
|
// Generate extension
|
||||||
ColorExtensionGenerator.writeExtensionFile(colors: parsedColors,
|
ColorExtensionGenerator.writeExtensionFile(colors: parsedColors,
|
||||||
staticVar: generateStaticVariable,
|
staticVar: options.staticMembers,
|
||||||
extensionName: options.extensionName,
|
extensionName: options.extensionNameSwiftUI,
|
||||||
extensionFilePath: extensionFilePath)
|
extensionFilePath: options.extensionFilePathSwiftUI,
|
||||||
|
isSwiftUI: true)
|
||||||
|
|
||||||
print("[\(Self.toolName)] Colors generated")
|
print("[\(Self.toolName)] Colors generated")
|
||||||
}
|
}
|
||||||
@ -79,20 +76,29 @@ struct ColorTool: ParsableCommand {
|
|||||||
|
|
||||||
// Check if input file exists
|
// Check if input file exists
|
||||||
guard fileManager.fileExists(atPath: options.inputFile) else {
|
guard fileManager.fileExists(atPath: options.inputFile) else {
|
||||||
let error = ColorToolError.fileNotExists(options.inputFile)
|
let error = ColorsToolError.fileNotExists(options.inputFile)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
ColorTool.exit(withError: error)
|
Colors.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if xcassets file exists
|
// Check if xcassets file exists
|
||||||
guard fileManager.fileExists(atPath: options.xcassetsPath) else {
|
guard fileManager.fileExists(atPath: options.xcassetsPath) else {
|
||||||
let error = ColorToolError.fileNotExists(options.xcassetsPath)
|
let error = ColorsToolError.fileNotExists(options.xcassetsPath)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
ColorTool.exit(withError: error)
|
Colors.exit(withError: error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension for UIKit and SwiftUI should have different name
|
||||||
|
guard options.extensionName != options.extensionNameSwiftUI else {
|
||||||
|
let error = ColorsToolError.extensionNamesCollision(options.extensionName)
|
||||||
|
print(error.description)
|
||||||
|
Colors.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if needed to regenerate
|
// Check if needed to regenerate
|
||||||
guard GeneratorChecker.shouldGenerate(force: options.forceGeneration, inputFilePath: options.inputFile, extensionFilePath: extensionFilePath) else {
|
guard GeneratorChecker.shouldGenerate(force: options.forceGeneration,
|
||||||
|
inputFilePath: options.inputFile,
|
||||||
|
extensionFilePath: options.extensionFilePath) else {
|
||||||
print("[\(Self.toolName)] Colors are already up to date :) ")
|
print("[\(Self.toolName)] Colors are already up to date :) ")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -103,21 +109,17 @@ struct ColorTool: ParsableCommand {
|
|||||||
// MARK: - Helpers
|
// MARK: - Helpers
|
||||||
|
|
||||||
private func deleteCurrentColors() {
|
private func deleteCurrentColors() {
|
||||||
Shell.shell("rm", "-rf", "\(options.xcassetsPath)/Colors/*")
|
let fileManager = FileManager()
|
||||||
|
let assetsColorPath = "\(options.xcassetsPath)/Colors"
|
||||||
|
|
||||||
|
if fileManager.fileExists(atPath: assetsColorPath) {
|
||||||
|
do {
|
||||||
|
try fileManager.removeItem(atPath: assetsColorPath)
|
||||||
|
} catch {
|
||||||
|
let error = ColorsToolError.deleteExistingColors("\(options.xcassetsPath)/Colors")
|
||||||
|
print(error.description)
|
||||||
|
Colors.exit(withError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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"
|
|
||||||
*/
|
|
47
Sources/ResgenSwift/Colors/ColorsToolError.swift
Normal file
47
Sources/ResgenSwift/Colors/ColorsToolError.swift
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
//
|
||||||
|
// ColorsToolError.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 20/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum ColorsToolError: Error {
|
||||||
|
case extensionNamesCollision(String)
|
||||||
|
case badFormat(String)
|
||||||
|
case writeAsset(String)
|
||||||
|
case createAssetFolder(String)
|
||||||
|
case writeExtension(String, String)
|
||||||
|
case fileNotExists(String)
|
||||||
|
case badColorDefinition(String, String)
|
||||||
|
case deleteExistingColors(String)
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .extensionNamesCollision(let extensionName):
|
||||||
|
return "error: [\(Fonts.toolName)] Error on extension names, extension name and SwiftUI extension name should be different (\(extensionName) is used on both)"
|
||||||
|
|
||||||
|
case .badFormat(let info):
|
||||||
|
return "error: [\(Colors.toolName)] Bad line format: \(info). Accepted format are: colorName=\"#RGB/#ARGB\"; colorName \"#RGB/#ARGB\"; colorName \"#RGB/#ARGB\" \"#RGB/#ARGB\""
|
||||||
|
|
||||||
|
case .writeAsset(let info):
|
||||||
|
return "error: [\(Colors.toolName)] An error occured while writing color in Xcasset: \(info)"
|
||||||
|
|
||||||
|
case .createAssetFolder(let assetsFolder):
|
||||||
|
return "error: [\(Colors.toolName)] An error occured while creating colors folder `\(assetsFolder)`"
|
||||||
|
|
||||||
|
case .writeExtension(let filename, let info):
|
||||||
|
return "error: [\(Colors.toolName)] An error occured while writing extension in \(filename): \(info)"
|
||||||
|
|
||||||
|
case .fileNotExists(let filename):
|
||||||
|
return "error: [\(Colors.toolName)] File \(filename) does not exists"
|
||||||
|
|
||||||
|
case .badColorDefinition(let lightColor, let darkColor):
|
||||||
|
return "error: [\(Colors.toolName)] One of these two colors has invalid synthax: -\(lightColor)- or -\(darkColor)-"
|
||||||
|
|
||||||
|
case .deleteExistingColors(let assetsFolder):
|
||||||
|
return "error: [\(Colors.toolName)] An error occured while deleting colors folder `\(assetsFolder)`"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
Sources/ResgenSwift/Colors/ColorsToolOptions.swift
Normal file
69
Sources/ResgenSwift/Colors/ColorsToolOptions.swift
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// ColorsToolOptions.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 17/01/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ArgumentParser
|
||||||
|
|
||||||
|
struct ColorsToolOptions: ParsableArguments {
|
||||||
|
@Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation")
|
||||||
|
var forceGeneration = false
|
||||||
|
|
||||||
|
@Argument(help: "Input files where colors ared defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||||
|
var inputFile: String
|
||||||
|
|
||||||
|
@Option(help: "Color style to generate: light for light colors only, or all for dark and light colors")
|
||||||
|
var style: ColorStyle
|
||||||
|
|
||||||
|
@Option(help: "Path of xcassets where to generate colors", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||||
|
var xcassetsPath: String
|
||||||
|
|
||||||
|
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||||
|
var extensionOutputPath: String
|
||||||
|
|
||||||
|
@Option(help: "Tell if it will generate static properties or not")
|
||||||
|
var staticMembers: Bool = false
|
||||||
|
|
||||||
|
@Option(help: "Extension name. If not specified, it will generate an UIColor extension.")
|
||||||
|
var extensionName: String = Colors.defaultExtensionName
|
||||||
|
|
||||||
|
@Option(help: "SwiftUI Extension name. If not specified, it will generate an Color extension.")
|
||||||
|
var extensionNameSwiftUI: String = Colors.defaultExtensionNameSUI
|
||||||
|
|
||||||
|
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+ColorsMyApp.swift")
|
||||||
|
var extensionSuffix: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Computed var
|
||||||
|
|
||||||
|
extension ColorsToolOptions {
|
||||||
|
|
||||||
|
// MARK: - UIKit
|
||||||
|
|
||||||
|
var extensionFileName: String {
|
||||||
|
if let extensionSuffix = extensionSuffix {
|
||||||
|
return "\(extensionName)+\(extensionSuffix).swift"
|
||||||
|
}
|
||||||
|
return "\(extensionName).swift"
|
||||||
|
}
|
||||||
|
|
||||||
|
var extensionFilePath: String {
|
||||||
|
"\(extensionOutputPath)/\(extensionFileName)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - SwiftUI
|
||||||
|
|
||||||
|
var extensionFileNameSwiftUI: String {
|
||||||
|
if let extensionSuffix = extensionSuffix {
|
||||||
|
return "\(extensionNameSwiftUI)+\(extensionSuffix).swift"
|
||||||
|
}
|
||||||
|
return "\(extensionNameSwiftUI).swift"
|
||||||
|
}
|
||||||
|
|
||||||
|
var extensionFilePathSwiftUI: String {
|
||||||
|
"\(extensionOutputPath)/\(extensionFileNameSwiftUI)"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
//
|
||||||
|
// ColorExtensionGenerator.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 20/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ToolCore
|
||||||
|
|
||||||
|
struct ColorExtensionGenerator {
|
||||||
|
|
||||||
|
let colors: [ParsedColor]
|
||||||
|
let extensionClassname: String
|
||||||
|
|
||||||
|
// MARK: - UIKit
|
||||||
|
|
||||||
|
static func writeExtensionFile(colors: [ParsedColor],
|
||||||
|
staticVar: Bool,
|
||||||
|
extensionName: String,
|
||||||
|
extensionFilePath: String,
|
||||||
|
isSwiftUI: Bool) {
|
||||||
|
// Create extension content
|
||||||
|
let extensionContent = Self.getExtensionContent(colors: colors,
|
||||||
|
staticVar: staticVar,
|
||||||
|
extensionName: extensionName,
|
||||||
|
isSwiftUI: isSwiftUI)
|
||||||
|
|
||||||
|
// Write content
|
||||||
|
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
|
||||||
|
do {
|
||||||
|
try extensionContent.write(to: extensionFilePathURL, atomically: false, encoding: .utf8)
|
||||||
|
} catch (let error) {
|
||||||
|
let error = ColorsToolError.writeExtension(extensionFilePath, error.localizedDescription)
|
||||||
|
print(error.description)
|
||||||
|
Colors.exit(withError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getExtensionContent(colors: [ParsedColor],
|
||||||
|
staticVar: Bool,
|
||||||
|
extensionName: String,
|
||||||
|
isSwiftUI: Bool) -> String {
|
||||||
|
[
|
||||||
|
Self.getHeader(extensionClassname: extensionName, isSwiftUI: isSwiftUI),
|
||||||
|
Self.getProperties(for: colors, withStaticVar: staticVar, isSwiftUI: isSwiftUI),
|
||||||
|
Self.getFooter()
|
||||||
|
]
|
||||||
|
.joined(separator: "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getHeader(extensionClassname: String, isSwiftUI: Bool) -> String {
|
||||||
|
"""
|
||||||
|
// Generated by ResgenSwift.\(Colors.toolName) \(ResgenSwiftVersion)
|
||||||
|
|
||||||
|
import \(isSwiftUI ? "SwiftUI" : "UIKit")
|
||||||
|
|
||||||
|
extension \(extensionClassname) {\n
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getFooter() -> String {
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getProperties(for colors: [ParsedColor],
|
||||||
|
withStaticVar staticVar: Bool,
|
||||||
|
isSwiftUI: Bool) -> String {
|
||||||
|
colors.map {
|
||||||
|
$0.getColorProperty(isStatic: staticVar, isSwiftUI: isSwiftUI)
|
||||||
|
}
|
||||||
|
.joined(separator: "\n\n")
|
||||||
|
}
|
||||||
|
}
|
@ -20,20 +20,28 @@ struct ColorXcassetHelper {
|
|||||||
private static func generateColorSetAssets(from color: ParsedColor, to xcassetsPath: String) {
|
private static func generateColorSetAssets(from color: ParsedColor, to xcassetsPath: String) {
|
||||||
// Create ColorSet
|
// Create ColorSet
|
||||||
let colorSetPath = "\(xcassetsPath)/Colors/\(color.name).colorset"
|
let colorSetPath = "\(xcassetsPath)/Colors/\(color.name).colorset"
|
||||||
Shell.shell("mkdir", "-p", "\(colorSetPath)")
|
|
||||||
|
|
||||||
// Create Contents.json in ColorSet
|
|
||||||
let contentsJsonPath = "\(colorSetPath)/Contents.json"
|
let contentsJsonPath = "\(colorSetPath)/Contents.json"
|
||||||
Shell.shell("touch", "\(contentsJsonPath)")
|
|
||||||
|
let fileManager = FileManager()
|
||||||
|
if fileManager.fileExists(atPath: colorSetPath) == false {
|
||||||
|
do {
|
||||||
|
try fileManager.createDirectory(atPath: colorSetPath,
|
||||||
|
withIntermediateDirectories: true)
|
||||||
|
} catch {
|
||||||
|
let error = ColorsToolError.createAssetFolder(colorSetPath)
|
||||||
|
print(error.description)
|
||||||
|
Colors.exit(withError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write content in Contents.json
|
// Write content in Contents.json
|
||||||
let contentsJsonPathURL = URL(fileURLWithPath: contentsJsonPath)
|
let contentsJsonPathURL = URL(fileURLWithPath: contentsJsonPath)
|
||||||
do {
|
do {
|
||||||
try color.contentsJSON().write(to: contentsJsonPathURL, atomically: true, encoding: .utf8)
|
try color.contentsJSON().write(to: contentsJsonPathURL, atomically: false, encoding: .utf8)
|
||||||
} catch (let error) {
|
} catch (let error) {
|
||||||
let error = ColorToolError.writeAsset(error.localizedDescription)
|
let error = ColorsToolError.writeAsset(error.localizedDescription)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
ColorTool.exit(withError: error)
|
Colors.exit(withError: error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
21
Sources/ResgenSwift/Colors/Model/ColorStyle.swift
Normal file
21
Sources/ResgenSwift/Colors/Model/ColorStyle.swift
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// ColorStyle.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 29/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ArgumentParser
|
||||||
|
|
||||||
|
enum ColorStyle: String, Decodable, ExpressibleByArgument {
|
||||||
|
case light
|
||||||
|
case all
|
||||||
|
|
||||||
|
static var allValueStrings: [String] {
|
||||||
|
[
|
||||||
|
Self.light.rawValue,
|
||||||
|
Self.all.rawValue
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -25,9 +25,9 @@ struct ParsedColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard allComponents.contains(true) == false else {
|
guard allComponents.contains(true) == false else {
|
||||||
let error = ColorToolError.badColorDefinition(light, dark)
|
let error = ColorsToolError.badColorDefinition(light, dark)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
ColorTool.exit(withError: error)
|
Colors.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return """
|
return """
|
||||||
@ -72,19 +72,20 @@ struct ParsedColor {
|
|||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
func getColorProperty() -> String {
|
// MARK: - UIKit
|
||||||
"""
|
|
||||||
|
func getColorProperty(isStatic: Bool, isSwiftUI: Bool) -> String {
|
||||||
|
if isSwiftUI {
|
||||||
|
return """
|
||||||
|
/// Color \(name) is \(light) (light) or \(dark) (dark)"
|
||||||
|
\(isStatic ? "static " : "")var \(name): Color {
|
||||||
|
Color("\(name)")
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
return """
|
||||||
/// Color \(name) is \(light) (light) or \(dark) (dark)"
|
/// Color \(name) is \(light) (light) or \(dark) (dark)"
|
||||||
@objc var \(name): UIColor {
|
\(isStatic ? "static " : "@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)")!
|
UIColor(named: "\(name)")!
|
||||||
}
|
}
|
||||||
"""
|
"""
|
56
Sources/ResgenSwift/Colors/Parser/ColorFileParser.swift
Normal file
56
Sources/ResgenSwift/Colors/Parser/ColorFileParser.swift
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// ColorFileParser.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 parseLines(lines: colorsByLines, colorStyle: colorStyle)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func parseLines(lines: [String], colorStyle: ColorStyle) -> [ParsedColor] {
|
||||||
|
lines
|
||||||
|
.enumerated()
|
||||||
|
.compactMap { lineNumber, colorLine in
|
||||||
|
// Required format:
|
||||||
|
// colorName = "#RGB/#ARGB", colorName "#RGB/#ARGB", colorName "#RGB/#ARGB" "#RGB/#ARGB"
|
||||||
|
let colorLineCleanedUp = colorLine
|
||||||
|
.removeLeadingWhitespace()
|
||||||
|
.removeTrailingWhitespace()
|
||||||
|
.replacingOccurrences(of: "=", with: "") // Keep compat with current file format
|
||||||
|
|
||||||
|
guard colorLineCleanedUp.hasPrefix("#") == false, colorLineCleanedUp.isEmpty == false else {
|
||||||
|
// debugPrint("[\(Colors.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 = ColorsToolError.badFormat(colorLine)
|
||||||
|
print(error.description)
|
||||||
|
Colors.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]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
74
Sources/ResgenSwift/Fonts/FontOptions.swift
Normal file
74
Sources/ResgenSwift/Fonts/FontOptions.swift
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
//
|
||||||
|
// FontsOptions.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 17/01/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ArgumentParser
|
||||||
|
|
||||||
|
struct FontsOptions: ParsableArguments {
|
||||||
|
@Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation")
|
||||||
|
var forceGeneration = false
|
||||||
|
|
||||||
|
@Argument(help: "Input files where fonts ared defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||||
|
var inputFile: String
|
||||||
|
|
||||||
|
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||||
|
var extensionOutputPath: String
|
||||||
|
|
||||||
|
@Option(help: "Tell if it will generate static properties or methods")
|
||||||
|
var staticMembers: Bool = false
|
||||||
|
|
||||||
|
@Option(help: "Extension name. If not specified, it will generate an UIFont extension.")
|
||||||
|
var extensionName: String = Fonts.defaultExtensionName
|
||||||
|
|
||||||
|
@Option(help: "Extension name. If not specified, it will generate an Font extension.")
|
||||||
|
var extensionNameSwiftUI: String = Fonts.defaultExtensionNameSUI
|
||||||
|
|
||||||
|
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+FontsMyApp.swift")
|
||||||
|
var extensionSuffix: String = ""
|
||||||
|
|
||||||
|
@Option(name: .customLong("info-plist-paths"), help: "Info.plist paths (array). Will be used to update UIAppFonts content")
|
||||||
|
fileprivate var infoPlistPathsRaw: String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Computed var
|
||||||
|
|
||||||
|
extension FontsOptions {
|
||||||
|
|
||||||
|
// MARK: - UIKit
|
||||||
|
|
||||||
|
var extensionFileName: String {
|
||||||
|
if extensionSuffix.isEmpty == false {
|
||||||
|
return "\(extensionName)+\(extensionSuffix).swift"
|
||||||
|
}
|
||||||
|
return "\(extensionName).swift"
|
||||||
|
}
|
||||||
|
|
||||||
|
var extensionFilePath: String {
|
||||||
|
"\(extensionOutputPath)/\(extensionFileName)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - SwiftUI
|
||||||
|
|
||||||
|
var extensionFileNameSwiftUI: String {
|
||||||
|
if extensionSuffix.isEmpty == false {
|
||||||
|
return "\(extensionNameSwiftUI)+\(extensionSuffix).swift"
|
||||||
|
}
|
||||||
|
return "\(extensionNameSwiftUI).swift"
|
||||||
|
}
|
||||||
|
|
||||||
|
var extensionFilePathSwiftUI: String {
|
||||||
|
"\(extensionOutputPath)/\(extensionFileNameSwiftUI)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: -
|
||||||
|
|
||||||
|
var infoPlistPaths: [String] {
|
||||||
|
infoPlistPathsRaw
|
||||||
|
.split(separator: " ")
|
||||||
|
.map { String($0) }
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// FontTool.swift
|
// Fonts.swift
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Created by Thibaut Schmitt on 13/12/2021.
|
// Created by Thibaut Schmitt on 13/12/2021.
|
||||||
@ -9,7 +9,7 @@ import ToolCore
|
|||||||
import Foundation
|
import Foundation
|
||||||
import ArgumentParser
|
import ArgumentParser
|
||||||
|
|
||||||
struct FontTool: ParsableCommand {
|
struct Fonts: ParsableCommand {
|
||||||
|
|
||||||
// MARK: - CommandConfiguration
|
// MARK: - CommandConfiguration
|
||||||
|
|
||||||
@ -20,30 +20,19 @@ struct FontTool: ParsableCommand {
|
|||||||
|
|
||||||
// MARK: - Static
|
// MARK: - Static
|
||||||
|
|
||||||
static let toolName = "FontTool"
|
static let toolName = "Fonts"
|
||||||
static let defaultExtensionName = "UIFont"
|
static let defaultExtensionName = "UIFont"
|
||||||
|
static let defaultExtensionNameSUI = "Font"
|
||||||
// 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
|
// MARK: - Command Options
|
||||||
|
|
||||||
@OptionGroup var options: FontOptions
|
@OptionGroup var options: FontsOptions
|
||||||
|
|
||||||
// MARK: - Run
|
// MARK: - Run
|
||||||
|
|
||||||
public func run() throws {
|
public func run() throws {
|
||||||
print("[\(Self.toolName)] Starting fonts generation")
|
print("[\(Self.toolName)] Starting fonts generation")
|
||||||
|
print("[\(Self.toolName)] Will use inputFile \(options.inputFile) to generate fonts")
|
||||||
|
|
||||||
// Check requirements
|
// Check requirements
|
||||||
guard checkRequirements() else { return }
|
guard checkRequirements() else { return }
|
||||||
@ -55,17 +44,24 @@ struct FontTool: ParsableCommand {
|
|||||||
|
|
||||||
// Get real font names
|
// Get real font names
|
||||||
let inputFolder = URL(fileURLWithPath: options.inputFile).deletingLastPathComponent().relativePath
|
let inputFolder = URL(fileURLWithPath: options.inputFile).deletingLastPathComponent().relativePath
|
||||||
let fontsNames = FontToolHelper.getFontPostScriptName(for: fontsToGenerate,
|
let fontsNames = FontsToolHelper.getFontPostScriptName(for: fontsToGenerate,
|
||||||
inputFolder: inputFolder)
|
inputFolder: inputFolder)
|
||||||
|
|
||||||
// Generate extension
|
// Generate extension
|
||||||
FontExtensionGenerator.writeExtensionFile(fontsNames: fontsNames,
|
FontExtensionGenerator.writeExtensionFile(fontsNames: fontsNames,
|
||||||
staticVar: generateStaticVariable,
|
staticVar: options.staticMembers,
|
||||||
extensionName: options.extensionName,
|
extensionName: options.extensionName,
|
||||||
extensionFilePath: extensionFilePath)
|
extensionFilePath: options.extensionFilePath,
|
||||||
|
isSwiftUI: false)
|
||||||
|
|
||||||
print("Info.plist information:")
|
FontExtensionGenerator.writeExtensionFile(fontsNames: fontsNames,
|
||||||
print("\(FontPlistGenerator.generatePlistUIAppsFontContent(for: fontsNames))")
|
staticVar: options.staticMembers,
|
||||||
|
extensionName: options.extensionNameSwiftUI,
|
||||||
|
extensionFilePath: options.extensionFilePathSwiftUI,
|
||||||
|
isSwiftUI: true)
|
||||||
|
|
||||||
|
print("Info.plist has been updated with:")
|
||||||
|
print("\(FontPlistGenerator.generatePlistUIAppsFontContent(for: fontsNames, infoPlistPaths: options.infoPlistPaths))")
|
||||||
|
|
||||||
print("[\(Self.toolName)] Fonts generated")
|
print("[\(Self.toolName)] Fonts generated")
|
||||||
}
|
}
|
||||||
@ -77,13 +73,22 @@ struct FontTool: ParsableCommand {
|
|||||||
|
|
||||||
// Check input file exists
|
// Check input file exists
|
||||||
guard fileManager.fileExists(atPath: options.inputFile) else {
|
guard fileManager.fileExists(atPath: options.inputFile) else {
|
||||||
let error = FontToolError.fileNotExists(options.inputFile)
|
let error = FontsToolError.fileNotExists(options.inputFile)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
FontTool.exit(withError: error)
|
Fonts.exit(withError: error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension for UIKit and SwiftUI should have different name
|
||||||
|
guard options.extensionName != options.extensionNameSwiftUI else {
|
||||||
|
let error = FontsToolError.extensionNamesCollision(options.extensionName)
|
||||||
|
print(error.description)
|
||||||
|
Fonts.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if needed to regenerate
|
// Check if needed to regenerate
|
||||||
guard GeneratorChecker.shouldGenerate(force: options.forceGeneration, inputFilePath: options.inputFile, extensionFilePath: extensionFilePath) else {
|
guard GeneratorChecker.shouldGenerate(force: options.forceGeneration,
|
||||||
|
inputFilePath: options.inputFile,
|
||||||
|
extensionFilePath: options.extensionFilePath) else {
|
||||||
print("[\(Self.toolName)] Fonts are already up to date :) ")
|
print("[\(Self.toolName)] Fonts are already up to date :) ")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -91,5 +96,3 @@ struct FontTool: ParsableCommand {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FontTool.main()
|
|
35
Sources/ResgenSwift/Fonts/FontsToolError.swift
Normal file
35
Sources/ResgenSwift/Fonts/FontsToolError.swift
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// FontsToolError.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 13/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum FontsToolError: Error {
|
||||||
|
case extensionNamesCollision(String)
|
||||||
|
case fcScan(String, Int32, String?)
|
||||||
|
case inputFolderNotFound(String)
|
||||||
|
case fileNotExists(String)
|
||||||
|
case writeExtension(String, String)
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .extensionNamesCollision(let extensionName):
|
||||||
|
return "error: [\(Fonts.toolName)] Error on extension names, extension name and SwiftUI extension name should be different (\(extensionName) is used on both)"
|
||||||
|
|
||||||
|
case .fcScan(let path, let code, let output):
|
||||||
|
return "error: [\(Fonts.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: [\(Fonts.toolName)] Input folder not found: \(inputFolder)"
|
||||||
|
|
||||||
|
case .fileNotExists(let filename):
|
||||||
|
return "error: [\(Fonts.toolName)] File \(filename) does not exists"
|
||||||
|
|
||||||
|
case .writeExtension(let filename, let info):
|
||||||
|
return "error: [\(Fonts.toolName)] An error occured while writing extension in \(filename): \(info)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// FontToolHelper.swift
|
// FontsToolHelper.swift
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Created by Thibaut Schmitt on 13/12/2021.
|
// Created by Thibaut Schmitt on 13/12/2021.
|
||||||
@ -8,7 +8,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import ToolCore
|
import ToolCore
|
||||||
|
|
||||||
class FontToolHelper {
|
class FontsToolHelper {
|
||||||
|
|
||||||
static func getFontPostScriptName(for fonts: [String], inputFolder: String) -> [FontName] {
|
static func getFontPostScriptName(for fonts: [String], inputFolder: String) -> [FontName] {
|
||||||
let fontsFilenames = Self.getFontsFilenames(fromInputFolder: inputFolder)
|
let fontsFilenames = Self.getFontsFilenames(fromInputFolder: inputFolder)
|
||||||
@ -38,9 +38,9 @@ class FontToolHelper {
|
|||||||
// Get a enumerator for all files
|
// Get a enumerator for all files
|
||||||
let fileManager = FileManager()
|
let fileManager = FileManager()
|
||||||
guard fileManager.fileExists(atPath: inputFolder) else {
|
guard fileManager.fileExists(atPath: inputFolder) else {
|
||||||
let error = FontToolError.inputFolderNotFound(inputFolder)
|
let error = FontsToolError.inputFolderNotFound(inputFolder)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
FontTool.exit(withError: error)
|
Fonts.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
let enumerator: FileManager.DirectoryEnumerator = fileManager.enumerator(atPath: inputFolder)!
|
let enumerator: FileManager.DirectoryEnumerator = fileManager.enumerator(atPath: inputFolder)!
|
||||||
@ -60,12 +60,12 @@ class FontToolHelper {
|
|||||||
private static func getFontName(atPath path: String) -> String {
|
private static func getFontName(atPath path: String) -> String {
|
||||||
//print("fc-scan --format %{postscriptname} \(path)")
|
//print("fc-scan --format %{postscriptname} \(path)")
|
||||||
// Get real font name
|
// Get real font name
|
||||||
let task = Shell.shell("fc-scan", "--format", "%{postscriptname}", path)
|
let task = Shell.shell(["fc-scan", "--format", "%{postscriptname}", path])
|
||||||
|
|
||||||
guard let fontName = task.output, task.terminationStatus == 0 else {
|
guard let fontName = task.output, task.terminationStatus == 0 else {
|
||||||
let error = FontToolError.fcScan(path, task.terminationStatus, task.output)
|
let error = FontsToolError.fcScan(path, task.terminationStatus, task.output)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
FontTool.exit(withError: error)
|
Fonts.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fontName
|
return fontName
|
44
Sources/ResgenSwift/Fonts/Generator/FontPlistGenerator.swift
Normal file
44
Sources/ResgenSwift/Fonts/Generator/FontPlistGenerator.swift
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// FontPlistGenerator.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 29/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ToolCore
|
||||||
|
|
||||||
|
class FontPlistGenerator {
|
||||||
|
static func generatePlistUIAppsFontContent(for fonts: [FontName], infoPlistPaths: [String]) -> String {
|
||||||
|
let fontsToAddToPlist = fonts
|
||||||
|
.compactMap { $0 }
|
||||||
|
|
||||||
|
// Update each plist
|
||||||
|
infoPlistPaths.forEach { infoPlist in
|
||||||
|
// Remove UIAppFonts value
|
||||||
|
Shell.shell(launchPath: "/usr/libexec/PlistBuddy",
|
||||||
|
["-c", "delete :UIAppFonts", infoPlist])
|
||||||
|
|
||||||
|
// Add UIAppFonts empty array
|
||||||
|
debugPrint("Will PlistBuddy -c add :UIAppFonts array \(infoPlist)")
|
||||||
|
Shell.shell(launchPath: "/usr/libexec/PlistBuddy",
|
||||||
|
["-c", "add :UIAppFonts array", infoPlist])
|
||||||
|
|
||||||
|
// Fill array with fonts
|
||||||
|
fontsToAddToPlist
|
||||||
|
.forEach {
|
||||||
|
Shell.shell(launchPath: "/usr/libexec/PlistBuddy",
|
||||||
|
["-c", "add :UIAppFonts: string \($0)", infoPlist])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var plistData = "<key>UIAppFonts</key>\n\t<array>\n"
|
||||||
|
fontsToAddToPlist
|
||||||
|
.forEach {
|
||||||
|
plistData += "\t\t<string>\($0)</string>\n"
|
||||||
|
}
|
||||||
|
plistData += "\t</array>"
|
||||||
|
|
||||||
|
return plistData
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
//
|
||||||
|
// FontToolContentGenerator.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 13/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ToolCore
|
||||||
|
|
||||||
|
class FontExtensionGenerator {
|
||||||
|
|
||||||
|
private static func getFontNameEnum(fontsNames: [String]) -> String {
|
||||||
|
var enumDefinition = " enum FontName: String {\n"
|
||||||
|
|
||||||
|
fontsNames.forEach {
|
||||||
|
enumDefinition += " case \($0.fontNameSanitize) = \"\($0)\"\n"
|
||||||
|
}
|
||||||
|
enumDefinition += " }\n"
|
||||||
|
|
||||||
|
return enumDefinition
|
||||||
|
}
|
||||||
|
|
||||||
|
static func writeExtensionFile(fontsNames: [String],
|
||||||
|
staticVar: Bool,
|
||||||
|
extensionName: String,
|
||||||
|
extensionFilePath: String,
|
||||||
|
isSwiftUI: Bool) {
|
||||||
|
// Create extension content
|
||||||
|
let extensionContent = Self.getExtensionContent(fontsNames: fontsNames,
|
||||||
|
staticVar: staticVar,
|
||||||
|
extensionName: extensionName,
|
||||||
|
isSwiftUI: isSwiftUI)
|
||||||
|
|
||||||
|
// Write content
|
||||||
|
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
|
||||||
|
do {
|
||||||
|
try extensionContent.write(to: extensionFilePathURL, atomically: false, encoding: .utf8)
|
||||||
|
} catch (let error) {
|
||||||
|
let error = FontsToolError.writeExtension(extensionFilePath, error.localizedDescription)
|
||||||
|
print(error.description)
|
||||||
|
Fonts.exit(withError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getExtensionContent(fontsNames: [String],
|
||||||
|
staticVar: Bool,
|
||||||
|
extensionName: String,
|
||||||
|
isSwiftUI: Bool) -> String {
|
||||||
|
[
|
||||||
|
Self.getHeader(extensionClassname: extensionName, isSwiftUI: isSwiftUI),
|
||||||
|
Self.getFontNameEnum(fontsNames: fontsNames),
|
||||||
|
Self.getFontMethods(fontsNames: fontsNames, staticVar: staticVar, isSwiftUI: isSwiftUI),
|
||||||
|
Self.getFooter()
|
||||||
|
]
|
||||||
|
.joined(separator: "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getHeader(extensionClassname: String, isSwiftUI: Bool) -> String {
|
||||||
|
"""
|
||||||
|
// Generated by ResgenSwift.\(Fonts.toolName) \(ResgenSwiftVersion)
|
||||||
|
|
||||||
|
import \(isSwiftUI ? "SwiftUI" : "UIKit")
|
||||||
|
|
||||||
|
extension \(extensionClassname) {\n
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getFontMethods(fontsNames: [FontName], staticVar: Bool, isSwiftUI: Bool) -> String {
|
||||||
|
let pragma = " // MARK: - Getter"
|
||||||
|
|
||||||
|
var propertiesOrMethods: [String] = fontsNames
|
||||||
|
.unique()
|
||||||
|
.map {
|
||||||
|
$0.getProperty(isStatic: staticVar, isSwiftUI: isSwiftUI)
|
||||||
|
}
|
||||||
|
|
||||||
|
propertiesOrMethods.insert(pragma, at: 0)
|
||||||
|
return propertiesOrMethods.joined(separator: "\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getFooter() -> String {
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
46
Sources/ResgenSwift/Fonts/Model/FontName.swift
Normal file
46
Sources/ResgenSwift/Fonts/Model/FontName.swift
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// FontName.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 29/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
typealias FontName = String
|
||||||
|
|
||||||
|
extension FontName {
|
||||||
|
var fontNameSanitize: String {
|
||||||
|
self.removeCharacters(from: "[]+-_")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProperty(isStatic: Bool, isSwiftUI: Bool) -> String {
|
||||||
|
if isSwiftUI {
|
||||||
|
if isStatic {
|
||||||
|
return """
|
||||||
|
static let \(fontNameSanitize): ((_ size: CGFloat) -> Font) = { size in
|
||||||
|
Font.custom(FontName.\(fontNameSanitize).rawValue, size: size)
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
return """
|
||||||
|
func \(fontNameSanitize)(withSize size: CGFloat) -> Font {
|
||||||
|
Font.custom(FontName.\(fontNameSanitize).rawValue, size: size)
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
// UIKit
|
||||||
|
if isStatic {
|
||||||
|
return """
|
||||||
|
static let \(fontNameSanitize): ((_ size: CGFloat) -> UIFont) = { size in
|
||||||
|
UIFont(name: FontName.\(fontNameSanitize).rawValue, size: size)!
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
return """
|
||||||
|
func \(fontNameSanitize)(withSize size: CGFloat) -> UIFont {
|
||||||
|
UIFont(name: FontName.\(fontNameSanitize).rawValue, size: size)!
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// File.swift
|
// FontFileParser.swift
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Created by Thibaut Schmitt on 29/08/2022.
|
// Created by Thibaut Schmitt on 29/08/2022.
|
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// StringExtensions.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 31/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
|
||||||
|
func prependIfRelativePath(_ prependPath: String) -> String {
|
||||||
|
// If path starts with "/", it's an absolute path
|
||||||
|
if self.hasPrefix("/") {
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
return prependPath + self
|
||||||
|
}
|
||||||
|
}
|
60
Sources/ResgenSwift/Generate/Generate.swift
Normal file
60
Sources/ResgenSwift/Generate/Generate.swift
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// Generate.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 30/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import ToolCore
|
||||||
|
import Foundation
|
||||||
|
import ArgumentParser
|
||||||
|
|
||||||
|
struct Generate: ParsableCommand {
|
||||||
|
|
||||||
|
// MARK: - CommandConfiguration
|
||||||
|
|
||||||
|
static var configuration = CommandConfiguration(
|
||||||
|
abstract: "A utility to generate ressources based on a configuration file",
|
||||||
|
version: ResgenSwiftVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
// MARK: - Static
|
||||||
|
|
||||||
|
static let toolName = "Generate"
|
||||||
|
|
||||||
|
// MARK: - Command Options
|
||||||
|
|
||||||
|
@OptionGroup var options: GenerateOptions
|
||||||
|
|
||||||
|
// MARK: - Run
|
||||||
|
|
||||||
|
public func run() throws {
|
||||||
|
print("[\(Self.toolName)] Starting Resgen with configuration: \(options.configurationFile)")
|
||||||
|
|
||||||
|
// Parse
|
||||||
|
let configuration = ConfigurationFileParser.parse(options.configurationFile)
|
||||||
|
print("Found configurations :")
|
||||||
|
print(" - \(configuration.colors.count) colors configuration(s)")
|
||||||
|
print(" - \(configuration.fonts.count) fonts configuration(s)")
|
||||||
|
print(" - \(configuration.images.count) images configuration(s)")
|
||||||
|
print(" - \(configuration.strings.count) strings configuration(s)")
|
||||||
|
print(" - \(configuration.tags.count) tags configuration(s)")
|
||||||
|
print()
|
||||||
|
|
||||||
|
if let architecture = configuration.architecture {
|
||||||
|
ArchitectureGenerator.writeArchitecture(architecture,
|
||||||
|
projectDirectory: options.projectDirectory)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute commands
|
||||||
|
configuration.runnableConfigurations
|
||||||
|
.forEach {
|
||||||
|
let begin = Date()
|
||||||
|
$0.run(projectDirectory: options.projectDirectory,
|
||||||
|
force: options.forceGeneration)
|
||||||
|
print("Took: \(Date().timeIntervalSince(begin))s\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
print("[\(Self.toolName)] Resgen ended")
|
||||||
|
}
|
||||||
|
}
|
34
Sources/ResgenSwift/Generate/GenerateError.swift
Normal file
34
Sources/ResgenSwift/Generate/GenerateError.swift
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// ResgenSwiftError.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 30/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum GenerateError: Error {
|
||||||
|
case fileNotExists(String)
|
||||||
|
case invalidConfigurationFile(String)
|
||||||
|
case commandError([String], String)
|
||||||
|
case writeFile(String, String)
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .fileNotExists(let filename):
|
||||||
|
return "error: [\(Generate.toolName)] File \(filename) does not exists"
|
||||||
|
|
||||||
|
case .invalidConfigurationFile(let filename):
|
||||||
|
return "error: [\(Generate.toolName)] File \(filename) is not a valid configuration file"
|
||||||
|
|
||||||
|
case .commandError(let command, let terminationStatus):
|
||||||
|
let readableCommand = command
|
||||||
|
.map { $0 }
|
||||||
|
.joined(separator: " ")
|
||||||
|
return "error: [\(Generate.toolName)] An error occured while running command '\(readableCommand)'. Command terminate with status code: \(terminationStatus)"
|
||||||
|
|
||||||
|
case .writeFile(let filename, let info):
|
||||||
|
return "error: [\(Generate.toolName)] An error occured while writing file in \(filename): \(info)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
Sources/ResgenSwift/Generate/GenerateOptions.swift
Normal file
28
Sources/ResgenSwift/Generate/GenerateOptions.swift
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// GenerateOptions.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 30/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ArgumentParser
|
||||||
|
|
||||||
|
struct GenerateOptions: ParsableArguments {
|
||||||
|
@Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation")
|
||||||
|
var forceGeneration = false
|
||||||
|
|
||||||
|
@Argument(help: "Configuration file.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||||
|
var configurationFile: String
|
||||||
|
|
||||||
|
@Option(help: "Project directory. It will be added to every relative path (path that does not start with `/`",
|
||||||
|
transform: {
|
||||||
|
if $0.last == "/" {
|
||||||
|
return $0
|
||||||
|
}
|
||||||
|
return $0 + "/"
|
||||||
|
})
|
||||||
|
var projectDirectory: String
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// ArchitectureGenerator.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 18/11/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import ToolCore
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct ArchitectureGenerator {
|
||||||
|
static func writeArchitecture(_ architecture: ConfigurationArchitecture, projectDirectory: String) {
|
||||||
|
// Create extension content
|
||||||
|
let architectureContent = [
|
||||||
|
"// Generated by ResgenSwift.\(Generate.toolName) \(ResgenSwiftVersion)",
|
||||||
|
architecture.getClass()
|
||||||
|
]
|
||||||
|
.joined(separator: "\n\n")
|
||||||
|
|
||||||
|
let filename = "\(architecture.classname).swift"
|
||||||
|
guard let filePath = architecture.path?.prependIfRelativePath(projectDirectory) else {
|
||||||
|
let error = GenerateError.writeFile(filename, "Path of file is not defined.")
|
||||||
|
print(error.description)
|
||||||
|
Generate.exit(withError: error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write content
|
||||||
|
let architectureFilePathURL = URL(fileURLWithPath: "\(filePath)/\(filename)")
|
||||||
|
do {
|
||||||
|
try architectureContent.write(to: architectureFilePathURL, atomically: false, encoding: .utf8)
|
||||||
|
} catch (let error) {
|
||||||
|
let error = GenerateError.writeFile(filename, error.localizedDescription)
|
||||||
|
print(error.description)
|
||||||
|
Generate.exit(withError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
306
Sources/ResgenSwift/Generate/Model/ConfigurationFile.swift
Normal file
306
Sources/ResgenSwift/Generate/Model/ConfigurationFile.swift
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
//
|
||||||
|
// ConfigurationFile.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 30/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct ConfigurationFile: Codable, CustomDebugStringConvertible {
|
||||||
|
var architecture: ConfigurationArchitecture?
|
||||||
|
var colors: [ColorsConfiguration]
|
||||||
|
var fonts: [FontsConfiguration]
|
||||||
|
var images: [ImagesConfiguration]
|
||||||
|
var strings: [StringsConfiguration]
|
||||||
|
var tags: [TagsConfiguration]
|
||||||
|
|
||||||
|
var runnableConfigurations: [Runnable] {
|
||||||
|
let runnables: [[Runnable]] = [colors, fonts, images, strings, tags]
|
||||||
|
return Array(runnables.joined())
|
||||||
|
}
|
||||||
|
|
||||||
|
var debugDescription: String {
|
||||||
|
"""
|
||||||
|
\(colors)
|
||||||
|
-----------
|
||||||
|
-----------
|
||||||
|
\(fonts)
|
||||||
|
-----------
|
||||||
|
-----------
|
||||||
|
\(images)
|
||||||
|
-----------
|
||||||
|
-----------
|
||||||
|
\(strings)
|
||||||
|
-----------
|
||||||
|
-----------
|
||||||
|
\(tags)
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConfigurationArchitecture: Codable {
|
||||||
|
let property: String
|
||||||
|
let classname: String
|
||||||
|
let path: String?
|
||||||
|
let children: [ConfigurationArchitecture]?
|
||||||
|
|
||||||
|
func getProperty(isStatic: Bool) -> String {
|
||||||
|
" \(isStatic ? "static " : "")let \(property) = \(classname)()"
|
||||||
|
}
|
||||||
|
|
||||||
|
func getClass(generateStaticProperty: Bool = true) -> String {
|
||||||
|
guard children?.isEmpty == false else {
|
||||||
|
return "class \(classname) {}"
|
||||||
|
}
|
||||||
|
|
||||||
|
let classDefinition = [
|
||||||
|
"class \(classname) {",
|
||||||
|
children?.map { $0.getProperty(isStatic: generateStaticProperty) }.joined(separator: "\n"),
|
||||||
|
"}"
|
||||||
|
]
|
||||||
|
.compactMap { $0 }
|
||||||
|
.joined(separator: "\n")
|
||||||
|
|
||||||
|
return [classDefinition, "", getSubclass()]
|
||||||
|
.compactMap { $0 }
|
||||||
|
.joined(separator: "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSubclass() -> String? {
|
||||||
|
guard let children else { return nil }
|
||||||
|
return children.compactMap { arch in
|
||||||
|
arch.getClass(generateStaticProperty: false)
|
||||||
|
}
|
||||||
|
.joined(separator: "\n\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ColorsConfiguration: Codable, CustomDebugStringConvertible {
|
||||||
|
let inputFile: String
|
||||||
|
let style: String
|
||||||
|
let xcassetsPath: String
|
||||||
|
let extensionOutputPath: String
|
||||||
|
let extensionName: String?
|
||||||
|
let extensionNameSwiftUI: String?
|
||||||
|
let extensionSuffix: String?
|
||||||
|
private let staticMembers: Bool?
|
||||||
|
|
||||||
|
var staticMembersOptions: Bool {
|
||||||
|
if let staticMembers = staticMembers {
|
||||||
|
return staticMembers
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
internal init(inputFile: String,
|
||||||
|
style: String,
|
||||||
|
xcassetsPath: String,
|
||||||
|
extensionOutputPath: String,
|
||||||
|
extensionName: String?,
|
||||||
|
extensionNameSwiftUI: String?,
|
||||||
|
extensionSuffix: String?,
|
||||||
|
staticMembers: Bool?) {
|
||||||
|
self.inputFile = inputFile
|
||||||
|
self.style = style
|
||||||
|
self.xcassetsPath = xcassetsPath
|
||||||
|
self.extensionOutputPath = extensionOutputPath
|
||||||
|
self.extensionName = extensionName
|
||||||
|
self.extensionNameSwiftUI = extensionNameSwiftUI
|
||||||
|
self.extensionSuffix = extensionSuffix
|
||||||
|
self.staticMembers = staticMembers
|
||||||
|
}
|
||||||
|
|
||||||
|
var debugDescription: String {
|
||||||
|
"""
|
||||||
|
Colors configuration:
|
||||||
|
- Input file: \(inputFile)
|
||||||
|
- Style: \(style)
|
||||||
|
- Xcassets path: \(xcassetsPath)
|
||||||
|
- Extension output path: \(extensionOutputPath)
|
||||||
|
- Extension name: \(extensionName ?? "-")
|
||||||
|
- Extension name SwiftUI: \(extensionNameSwiftUI ?? "-")
|
||||||
|
- Extension suffix: \(extensionSuffix ?? "-")
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FontsConfiguration: Codable, CustomDebugStringConvertible {
|
||||||
|
let inputFile: String
|
||||||
|
let extensionOutputPath: String
|
||||||
|
let extensionName: String?
|
||||||
|
let extensionNameSwiftUI: String?
|
||||||
|
let extensionSuffix: String?
|
||||||
|
let infoPlistPaths: String?
|
||||||
|
private let staticMembers: Bool?
|
||||||
|
|
||||||
|
var staticMembersOptions: Bool {
|
||||||
|
if let staticMembers = staticMembers {
|
||||||
|
return staticMembers
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
internal init(inputFile: String,
|
||||||
|
extensionOutputPath: String,
|
||||||
|
extensionName: String?,
|
||||||
|
extensionNameSwiftUI: String?,
|
||||||
|
extensionSuffix: String?,
|
||||||
|
infoPlistPaths: String?,
|
||||||
|
staticMembers: Bool?) {
|
||||||
|
self.inputFile = inputFile
|
||||||
|
self.extensionOutputPath = extensionOutputPath
|
||||||
|
self.extensionName = extensionName
|
||||||
|
self.extensionNameSwiftUI = extensionNameSwiftUI
|
||||||
|
self.extensionSuffix = extensionSuffix
|
||||||
|
self.infoPlistPaths = infoPlistPaths
|
||||||
|
self.staticMembers = staticMembers
|
||||||
|
}
|
||||||
|
|
||||||
|
var debugDescription: String {
|
||||||
|
"""
|
||||||
|
Fonts configuration:
|
||||||
|
- Input file: \(inputFile)
|
||||||
|
- Extension output path: \(extensionOutputPath)
|
||||||
|
- Extension name: \(extensionName ?? "-")
|
||||||
|
- Extension name SwiftUI: \(extensionNameSwiftUI ?? "-")
|
||||||
|
- Extension suffix: \(extensionSuffix ?? "-")
|
||||||
|
- InfoPlistPaths: \(infoPlistPaths ?? "-")
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ImagesConfiguration: Codable, CustomDebugStringConvertible {
|
||||||
|
let inputFile: String
|
||||||
|
let xcassetsPath: String
|
||||||
|
let extensionOutputPath: String
|
||||||
|
let extensionName: String?
|
||||||
|
let extensionNameSwiftUI: String?
|
||||||
|
let extensionSuffix: String?
|
||||||
|
private let staticMembers: Bool?
|
||||||
|
|
||||||
|
var staticMembersOptions: Bool {
|
||||||
|
if let staticMembers = staticMembers {
|
||||||
|
return staticMembers
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
internal init(inputFile: String,
|
||||||
|
xcassetsPath: String,
|
||||||
|
extensionOutputPath: String,
|
||||||
|
extensionName: String?,
|
||||||
|
extensionNameSwiftUI: String?,
|
||||||
|
extensionSuffix: String?,
|
||||||
|
staticMembers: Bool?) {
|
||||||
|
self.inputFile = inputFile
|
||||||
|
self.xcassetsPath = xcassetsPath
|
||||||
|
self.extensionOutputPath = extensionOutputPath
|
||||||
|
self.extensionName = extensionName
|
||||||
|
self.extensionNameSwiftUI = extensionNameSwiftUI
|
||||||
|
self.extensionSuffix = extensionSuffix
|
||||||
|
self.staticMembers = staticMembers
|
||||||
|
}
|
||||||
|
|
||||||
|
var debugDescription: String {
|
||||||
|
"""
|
||||||
|
Images configuration:
|
||||||
|
- Input file: \(inputFile)
|
||||||
|
- Xcassets path: \(xcassetsPath)
|
||||||
|
- Extension output path: \(extensionOutputPath)
|
||||||
|
- Extension name: \(extensionName ?? "-")
|
||||||
|
- Extension name SwiftUI: \(extensionNameSwiftUI ?? "-")
|
||||||
|
- Extension suffix: \(extensionSuffix ?? "-")
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StringsConfiguration: Codable, CustomDebugStringConvertible {
|
||||||
|
let inputFile: String
|
||||||
|
let outputPath: String
|
||||||
|
let langs: String
|
||||||
|
let defaultLang: String
|
||||||
|
let extensionOutputPath: String
|
||||||
|
let extensionName: String?
|
||||||
|
let extensionSuffix: String?
|
||||||
|
private let staticMembers: Bool?
|
||||||
|
|
||||||
|
var staticMembersOptions: Bool {
|
||||||
|
if let staticMembers = staticMembers {
|
||||||
|
return staticMembers
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
internal init(inputFile: String,
|
||||||
|
outputPath: String,
|
||||||
|
langs: String,
|
||||||
|
defaultLang: String,
|
||||||
|
extensionOutputPath: String,
|
||||||
|
extensionName: String?,
|
||||||
|
extensionSuffix: String?,
|
||||||
|
staticMembers: Bool?) {
|
||||||
|
self.inputFile = inputFile
|
||||||
|
self.outputPath = outputPath
|
||||||
|
self.langs = langs
|
||||||
|
self.defaultLang = defaultLang
|
||||||
|
self.extensionOutputPath = extensionOutputPath
|
||||||
|
self.extensionName = extensionName
|
||||||
|
self.extensionSuffix = extensionSuffix
|
||||||
|
self.staticMembers = staticMembers
|
||||||
|
}
|
||||||
|
|
||||||
|
var debugDescription: String {
|
||||||
|
"""
|
||||||
|
Strings configuration:
|
||||||
|
- Input file: \(inputFile)
|
||||||
|
- Output path: \(outputPath)
|
||||||
|
- Langs: \(langs)
|
||||||
|
- Default lang: \(defaultLang)
|
||||||
|
- Extension output path: \(extensionOutputPath)
|
||||||
|
- Extension name: \(extensionName ?? "-")
|
||||||
|
- Extension suffix: \(extensionSuffix ?? "-")
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TagsConfiguration: Codable, CustomDebugStringConvertible {
|
||||||
|
let inputFile: String
|
||||||
|
let lang: String
|
||||||
|
let extensionOutputPath: String
|
||||||
|
let extensionName: String?
|
||||||
|
let extensionSuffix: String?
|
||||||
|
private let staticMembers: Bool?
|
||||||
|
|
||||||
|
var staticMembersOptions: Bool {
|
||||||
|
if let staticMembers = staticMembers {
|
||||||
|
return staticMembers
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
internal init(inputFile: String,
|
||||||
|
lang: String,
|
||||||
|
extensionOutputPath: String,
|
||||||
|
extensionName: String?,
|
||||||
|
extensionSuffix: String?,
|
||||||
|
staticMembers: Bool?) {
|
||||||
|
self.inputFile = inputFile
|
||||||
|
self.lang = lang
|
||||||
|
self.extensionOutputPath = extensionOutputPath
|
||||||
|
self.extensionName = extensionName
|
||||||
|
self.extensionSuffix = extensionSuffix
|
||||||
|
self.staticMembers = staticMembers
|
||||||
|
}
|
||||||
|
|
||||||
|
var debugDescription: String {
|
||||||
|
"""
|
||||||
|
Tags configuration:
|
||||||
|
- Input file: \(inputFile)
|
||||||
|
- Lang: \(lang)
|
||||||
|
- Extension output path: \(extensionOutputPath)
|
||||||
|
- Extension name: \(extensionName ?? "-")
|
||||||
|
- Extension suffix: \(extensionSuffix ?? "-")
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// ConfigurationFileParser.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 30/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Yams
|
||||||
|
|
||||||
|
class ConfigurationFileParser {
|
||||||
|
static func parse(_ configurationFile: String) -> ConfigurationFile {
|
||||||
|
guard let data = FileManager().contents(atPath: configurationFile) else {
|
||||||
|
let error = GenerateError.fileNotExists(configurationFile)
|
||||||
|
print(error.description)
|
||||||
|
Generate.exit(withError: error)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let configuration = try? YAMLDecoder().decode(ConfigurationFile.self, from: data) else {
|
||||||
|
let error = GenerateError.invalidConfigurationFile(configurationFile)
|
||||||
|
print(error.description)
|
||||||
|
Generate.exit(withError: error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return configuration
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// ColorsConfiguration+Runnable.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 30/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension ColorsConfiguration: Runnable {
|
||||||
|
func run(projectDirectory: String, force: Bool) {
|
||||||
|
let args = getArguments(projectDirectory: projectDirectory, force: force)
|
||||||
|
Colors.main(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArguments(projectDirectory: String, force: Bool) -> [String] {
|
||||||
|
var args = [String]()
|
||||||
|
|
||||||
|
if force {
|
||||||
|
args += ["-f"]
|
||||||
|
}
|
||||||
|
|
||||||
|
args += [
|
||||||
|
inputFile.prependIfRelativePath(projectDirectory),
|
||||||
|
"--style",
|
||||||
|
style,
|
||||||
|
"--xcassets-path",
|
||||||
|
xcassetsPath.prependIfRelativePath(projectDirectory),
|
||||||
|
"--extension-output-path",
|
||||||
|
extensionOutputPath.prependIfRelativePath(projectDirectory),
|
||||||
|
"--static-members",
|
||||||
|
"\(staticMembersOptions)"
|
||||||
|
]
|
||||||
|
|
||||||
|
if let extensionName = extensionName {
|
||||||
|
args += [
|
||||||
|
"--extension-name",
|
||||||
|
extensionName
|
||||||
|
]
|
||||||
|
}
|
||||||
|
if let extensionNameSwiftUI = extensionNameSwiftUI {
|
||||||
|
args += [
|
||||||
|
"--extension-name-swift-ui",
|
||||||
|
extensionNameSwiftUI
|
||||||
|
]
|
||||||
|
}
|
||||||
|
if let extensionSuffix = extensionSuffix {
|
||||||
|
args += [
|
||||||
|
"--extension-suffix",
|
||||||
|
extensionSuffix
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
//
|
||||||
|
// FontsConfiguration+Runnable.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 30/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension FontsConfiguration: Runnable {
|
||||||
|
func run(projectDirectory: String, force: Bool) {
|
||||||
|
let args = getArguments(projectDirectory: projectDirectory, force: force)
|
||||||
|
Fonts.main(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArguments(projectDirectory: String, force: Bool) -> [String] {
|
||||||
|
var args = [String]()
|
||||||
|
|
||||||
|
if force {
|
||||||
|
args += ["-f"]
|
||||||
|
}
|
||||||
|
|
||||||
|
args += [
|
||||||
|
inputFile.prependIfRelativePath(projectDirectory),
|
||||||
|
"--extension-output-path",
|
||||||
|
extensionOutputPath.prependIfRelativePath(projectDirectory),
|
||||||
|
"--static-members",
|
||||||
|
"\(staticMembersOptions)"
|
||||||
|
]
|
||||||
|
|
||||||
|
if let extensionName = extensionName {
|
||||||
|
args += [
|
||||||
|
"--extension-name",
|
||||||
|
extensionName
|
||||||
|
]
|
||||||
|
}
|
||||||
|
if let extensionNameSwiftUI = extensionNameSwiftUI {
|
||||||
|
args += [
|
||||||
|
"--extension-name-swift-ui",
|
||||||
|
extensionNameSwiftUI
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if let extensionSuffix = extensionSuffix {
|
||||||
|
args += [
|
||||||
|
"--extension-suffix",
|
||||||
|
extensionSuffix
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if let infoPlistPaths = infoPlistPaths {
|
||||||
|
let adjustedPlistPaths = infoPlistPaths
|
||||||
|
.split(separator: " ")
|
||||||
|
.map { String($0).prependIfRelativePath(projectDirectory) }
|
||||||
|
.joined(separator: " ")
|
||||||
|
|
||||||
|
args += [
|
||||||
|
"--info-plist-paths",
|
||||||
|
adjustedPlistPaths
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// ImagesConfiguration+Runnable.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 30/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension ImagesConfiguration: Runnable {
|
||||||
|
func run(projectDirectory: String, force: Bool) {
|
||||||
|
let args = getArguments(projectDirectory: projectDirectory, force: force)
|
||||||
|
Images.main(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArguments(projectDirectory: String, force: Bool) -> [String] {
|
||||||
|
var args = [String]()
|
||||||
|
|
||||||
|
if force {
|
||||||
|
args += ["-f"] // Images has a -f and -F options
|
||||||
|
}
|
||||||
|
|
||||||
|
args += [
|
||||||
|
inputFile.prependIfRelativePath(projectDirectory),
|
||||||
|
"--xcassets-path",
|
||||||
|
xcassetsPath.prependIfRelativePath(projectDirectory),
|
||||||
|
"--extension-output-path",
|
||||||
|
extensionOutputPath.prependIfRelativePath(projectDirectory),
|
||||||
|
"--static-members",
|
||||||
|
"\(staticMembersOptions)"
|
||||||
|
]
|
||||||
|
|
||||||
|
if let extensionName = extensionName {
|
||||||
|
args += [
|
||||||
|
"--extension-name",
|
||||||
|
extensionName
|
||||||
|
]
|
||||||
|
}
|
||||||
|
if let extensionNameSwiftUI = extensionNameSwiftUI {
|
||||||
|
args += [
|
||||||
|
"--extension-name-swift-ui",
|
||||||
|
extensionNameSwiftUI
|
||||||
|
]
|
||||||
|
}
|
||||||
|
if let extensionSuffix = extensionSuffix {
|
||||||
|
args += [
|
||||||
|
"--extension-suffix",
|
||||||
|
extensionSuffix
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
}
|
13
Sources/ResgenSwift/Generate/Runnable/Runnable.swift
Normal file
13
Sources/ResgenSwift/Generate/Runnable/Runnable.swift
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// ShellCommandable.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 30/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
protocol Runnable {
|
||||||
|
func run(projectDirectory: String, force: Bool)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// StringsConfiguration+Runnable.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 30/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension StringsConfiguration: Runnable {
|
||||||
|
func run(projectDirectory: String, force: Bool) {
|
||||||
|
var args = [String]()
|
||||||
|
|
||||||
|
if force {
|
||||||
|
args += ["-f"]
|
||||||
|
}
|
||||||
|
|
||||||
|
args += [
|
||||||
|
inputFile.prependIfRelativePath(projectDirectory),
|
||||||
|
"--output-path",
|
||||||
|
outputPath.prependIfRelativePath(projectDirectory),
|
||||||
|
"--langs",
|
||||||
|
langs,
|
||||||
|
"--default-lang",
|
||||||
|
defaultLang,
|
||||||
|
"--extension-output-path",
|
||||||
|
extensionOutputPath.prependIfRelativePath(projectDirectory),
|
||||||
|
"--static-members",
|
||||||
|
"\(staticMembersOptions)"
|
||||||
|
]
|
||||||
|
|
||||||
|
if let extensionName = extensionName {
|
||||||
|
args += [
|
||||||
|
"--extension-name",
|
||||||
|
extensionName
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if let extensionSuffix = extensionSuffix {
|
||||||
|
args += [
|
||||||
|
"--extension-suffix",
|
||||||
|
extensionSuffix
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Stringium.main(args)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// TagsConfiguration+Runnable.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 30/08/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension TagsConfiguration: Runnable {
|
||||||
|
func run(projectDirectory: String, force: Bool) {
|
||||||
|
var args = [String]()
|
||||||
|
|
||||||
|
if force {
|
||||||
|
args += ["-f"]
|
||||||
|
}
|
||||||
|
|
||||||
|
args += [
|
||||||
|
inputFile.prependIfRelativePath(projectDirectory),
|
||||||
|
"--lang",
|
||||||
|
lang,
|
||||||
|
"--extension-output-path",
|
||||||
|
extensionOutputPath.prependIfRelativePath(projectDirectory),
|
||||||
|
"--static-members",
|
||||||
|
"\(staticMembersOptions)"
|
||||||
|
]
|
||||||
|
|
||||||
|
if let extensionName = extensionName {
|
||||||
|
args += [
|
||||||
|
"--extension-name",
|
||||||
|
extensionName
|
||||||
|
]
|
||||||
|
}
|
||||||
|
if let extensionSuffix = extensionSuffix {
|
||||||
|
args += [
|
||||||
|
"--extension-suffix",
|
||||||
|
extensionSuffix
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Tags.main(args)
|
||||||
|
}
|
||||||
|
}
|
@ -11,9 +11,9 @@ extension FileManager {
|
|||||||
func getAllRegularFileIn(directory: String) -> [String] {
|
func getAllRegularFileIn(directory: String) -> [String] {
|
||||||
var files = [String]()
|
var files = [String]()
|
||||||
guard let enumerator = self.enumerator(at: URL(string: directory)!, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) else {
|
guard let enumerator = self.enumerator(at: URL(string: directory)!, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) else {
|
||||||
let error = ImagiumError.unknown("Cannot enumerate file in \(directory)")
|
let error = ImagesError.unknown("Cannot enumerate file in \(directory)")
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Imagium.exit(withError: error)
|
Images.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
for case let fileURL as URL in enumerator {
|
for case let fileURL as URL in enumerator {
|
||||||
@ -23,9 +23,9 @@ extension FileManager {
|
|||||||
files.append(fileURL.relativePath)
|
files.append(fileURL.relativePath)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
let error = ImagiumError.getFileAttributed(fileURL.relativePath, error.localizedDescription)
|
let error = ImagesError.getFileAttributed(fileURL.relativePath, error.localizedDescription)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Imagium.exit(withError: error)
|
Images.exit(withError: error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return files
|
return files
|
||||||
@ -34,9 +34,9 @@ extension FileManager {
|
|||||||
func getAllImageSetFolderIn(directory: String) -> [String] {
|
func getAllImageSetFolderIn(directory: String) -> [String] {
|
||||||
var files = [String]()
|
var files = [String]()
|
||||||
guard let enumerator = self.enumerator(at: URL(string: directory)!, includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) else {
|
guard let enumerator = self.enumerator(at: URL(string: directory)!, includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) else {
|
||||||
let error = ImagiumError.unknown("Cannot enumerate imageset directory in \(directory)")
|
let error = ImagesError.unknown("Cannot enumerate imageset directory in \(directory)")
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Imagium.exit(withError: error)
|
Images.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
for case let fileURL as URL in enumerator {
|
for case let fileURL as URL in enumerator {
|
||||||
@ -46,9 +46,9 @@ extension FileManager {
|
|||||||
files.append(fileURL.lastPathComponent)
|
files.append(fileURL.lastPathComponent)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
let error = ImagiumError.getFileAttributed(fileURL.relativePath, error.localizedDescription)
|
let error = ImagesError.getFileAttributed(fileURL.relativePath, error.localizedDescription)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Imagium.exit(withError: error)
|
Images.exit(withError: error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return files
|
return files
|
@ -0,0 +1,77 @@
|
|||||||
|
//
|
||||||
|
// ImageExtensionGenerator.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 14/02/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import ToolCore
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class ImageExtensionGenerator {
|
||||||
|
|
||||||
|
// MARK: - UIKit
|
||||||
|
|
||||||
|
static func generateExtensionFile(images: [ParsedImage],
|
||||||
|
staticVar: Bool,
|
||||||
|
inputFilename: String,
|
||||||
|
extensionName: String,
|
||||||
|
extensionFilePath: String,
|
||||||
|
isSwiftUI: Bool) {
|
||||||
|
// Create extension conten1t
|
||||||
|
let extensionContent = Self.getExtensionContent(images: images,
|
||||||
|
staticVar: staticVar,
|
||||||
|
extensionName: extensionName,
|
||||||
|
inputFilename: inputFilename,
|
||||||
|
isSwiftUI: isSwiftUI)
|
||||||
|
|
||||||
|
// Write content
|
||||||
|
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
|
||||||
|
do {
|
||||||
|
try extensionContent.write(to: extensionFilePathURL, atomically: false, encoding: .utf8)
|
||||||
|
} catch (let error) {
|
||||||
|
let error = ImagesError.writeFile(extensionFilePath, error.localizedDescription)
|
||||||
|
print(error.description)
|
||||||
|
Images.exit(withError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getExtensionContent(images: [ParsedImage],
|
||||||
|
staticVar: Bool,
|
||||||
|
extensionName: String,
|
||||||
|
inputFilename: String,
|
||||||
|
isSwiftUI: Bool) -> String {
|
||||||
|
[
|
||||||
|
Self.getHeader(inputFilename: inputFilename, extensionClassname: extensionName, isSwiftUI: isSwiftUI),
|
||||||
|
Self.getProperties(images: images, staticVar: staticVar, isSwiftUI: isSwiftUI),
|
||||||
|
Self.getFooter()
|
||||||
|
]
|
||||||
|
.joined(separator: "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getHeader(inputFilename: String,
|
||||||
|
extensionClassname: String,
|
||||||
|
isSwiftUI: Bool) -> String {
|
||||||
|
"""
|
||||||
|
// Generated by ResgenSwift.\(Images.toolName) \(ResgenSwiftVersion)
|
||||||
|
// Images from \(inputFilename)
|
||||||
|
|
||||||
|
import \(isSwiftUI ? "SwiftUI" : "UIKit")
|
||||||
|
|
||||||
|
extension \(extensionClassname) {
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getProperties(images: [ParsedImage], staticVar: Bool, isSwiftUI: Bool) -> String {
|
||||||
|
images
|
||||||
|
.map { "\n\($0.getImageProperty(isStatic: staticVar, isSwiftUI: isSwiftUI))" }
|
||||||
|
.joined(separator: "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getFooter() -> String {
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// File.swift
|
// XcassetsGenerator.swift
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Created by Thibaut Schmitt on 24/01/2022.
|
// Created by Thibaut Schmitt on 24/01/2022.
|
||||||
@ -24,7 +24,7 @@ class XcassetsGenerator {
|
|||||||
|
|
||||||
func generateXcassets(inputPath: String, imagesToGenerate: [ParsedImage], xcassetsPath: String) {
|
func generateXcassets(inputPath: String, imagesToGenerate: [ParsedImage], xcassetsPath: String) {
|
||||||
let fileManager = FileManager()
|
let fileManager = FileManager()
|
||||||
let svgConverter = Imagium.getSvgConverterPath()
|
let svgConverter = Images.getSvgConverterPath()
|
||||||
let allSubFiles = fileManager.getAllRegularFileIn(directory: inputPath)
|
let allSubFiles = fileManager.getAllRegularFileIn(directory: inputPath)
|
||||||
|
|
||||||
var generatedAssetsPaths = [String]()
|
var generatedAssetsPaths = [String]()
|
||||||
@ -47,15 +47,14 @@ class XcassetsGenerator {
|
|||||||
return (subfile, "jepg")
|
return (subfile, "jepg")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let error = ImagiumError.unknownImageExtension(parsedImage.name)
|
let error = ImagesError.unknownImageExtension(parsedImage.name)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Imagium.exit(withError: error)
|
Images.exit(withError: error)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Create imageset folder
|
// Create imageset folder name
|
||||||
let imagesetName = "\(parsedImage.name).imageset"
|
let imagesetName = "\(parsedImage.name).imageset"
|
||||||
let imagesetPath = "\(xcassetsPath)/\(imagesetName)"
|
let imagesetPath = "\(xcassetsPath)/\(imagesetName)"
|
||||||
Shell.shell("mkdir", "-p", imagesetPath)
|
|
||||||
|
|
||||||
// Store managed images path
|
// Store managed images path
|
||||||
generatedAssetsPaths.append(imagesetName)
|
generatedAssetsPaths.append(imagesetName)
|
||||||
@ -66,11 +65,23 @@ class XcassetsGenerator {
|
|||||||
let output3x = "\(imagesetPath)/\(parsedImage.name)@3x.\(XcassetsGenerator.outputImageExtension)"
|
let output3x = "\(imagesetPath)/\(parsedImage.name)@3x.\(XcassetsGenerator.outputImageExtension)"
|
||||||
|
|
||||||
// Check if we need to convert image
|
// Check if we need to convert image
|
||||||
if self.shouldBypassGeneration(for: parsedImage, xcassetImagePath: output1x) {
|
guard self.shouldGenerate(inputImagePath: imageData.path, xcassetImagePath: output1x) else {
|
||||||
print("\(parsedImage.name) -> Not regenerating")
|
//print("\(parsedImage.name) -> Not regenerating")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create imageset folder
|
||||||
|
if fileManager.fileExists(atPath: imagesetPath) == false {
|
||||||
|
do {
|
||||||
|
try fileManager.createDirectory(atPath: imagesetPath,
|
||||||
|
withIntermediateDirectories: true)
|
||||||
|
} catch {
|
||||||
|
let error = ImagesError.createAssetFolder(imagesetPath)
|
||||||
|
print(error.description)
|
||||||
|
Images.exit(withError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Convert image
|
// Convert image
|
||||||
let convertArguments = parsedImage.convertArguments
|
let convertArguments = parsedImage.convertArguments
|
||||||
if imageData.ext == "svg" {
|
if imageData.ext == "svg" {
|
||||||
@ -96,20 +107,23 @@ class XcassetsGenerator {
|
|||||||
// convert path/to/image.png -resize 200x300 path/to/output.png
|
// convert path/to/image.png -resize 200x300 path/to/output.png
|
||||||
// convert path/to/image.png -resize 200x path/to/output.png
|
// convert path/to/image.png -resize 200x path/to/output.png
|
||||||
// convert path/to/image.png -resize x300 path/to/output.png
|
// convert path/to/image.png -resize x300 path/to/output.png
|
||||||
Shell.shell("convert", "\(imageData.path)", "-resize", "\(convertArguments.x1.width ?? "")x\(convertArguments.x1.height ?? "")", output1x)
|
Shell.shell(["convert", "\(imageData.path)",
|
||||||
Shell.shell("convert", "\(imageData.path)", "-resize", "\(convertArguments.x2.width ?? "")x\(convertArguments.x2.height ?? "")", output2x)
|
"-resize", "\(convertArguments.x1.width ?? "")x\(convertArguments.x1.height ?? "")",
|
||||||
Shell.shell("convert", "\(imageData.path)", "-resize", "\(convertArguments.x3.width ?? "")x\(convertArguments.x3.height ?? "")", output3x)
|
output1x])
|
||||||
|
Shell.shell(["convert", "\(imageData.path)",
|
||||||
|
"-resize", "\(convertArguments.x2.width ?? "")x\(convertArguments.x2.height ?? "")",
|
||||||
|
output2x])
|
||||||
|
Shell.shell(["convert", "\(imageData.path)",
|
||||||
|
"-resize", "\(convertArguments.x3.width ?? "")x\(convertArguments.x3.height ?? "")",
|
||||||
|
output3x])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write Content.json
|
// Write Content.json
|
||||||
let imagesetContentJson = parsedImage.contentJson
|
let imagesetContentJson = parsedImage.contentJson
|
||||||
let contentJsonFilePath = "\(imagesetPath)/Contents.json"
|
let contentJsonFilePath = "\(imagesetPath)/Contents.json"
|
||||||
if fileManager.fileExists(atPath: contentJsonFilePath) == false {
|
|
||||||
Shell.shell("touch", "\(contentJsonFilePath)")
|
|
||||||
}
|
|
||||||
|
|
||||||
let contentJsonFilePathURL = URL(fileURLWithPath: contentJsonFilePath)
|
let contentJsonFilePathURL = URL(fileURLWithPath: contentJsonFilePath)
|
||||||
try! imagesetContentJson.write(to: contentJsonFilePathURL, atomically: true, encoding: .utf8)
|
try! imagesetContentJson.write(to: contentJsonFilePathURL, atomically: false, encoding: .utf8)
|
||||||
|
|
||||||
print("\(parsedImage.name) -> Generated")
|
print("\(parsedImage.name) -> Generated")
|
||||||
}
|
}
|
||||||
@ -147,43 +161,11 @@ class XcassetsGenerator {
|
|||||||
|
|
||||||
// MARK: - Helpers: bypass generation
|
// MARK: - Helpers: bypass generation
|
||||||
|
|
||||||
private func shouldBypassGeneration(for image: ParsedImage, xcassetImagePath: String) -> Bool {
|
private func shouldGenerate(inputImagePath: String, xcassetImagePath: String) -> Bool {
|
||||||
guard forceGeneration == false else {
|
if forceGeneration {
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
let fileManager = FileManager()
|
|
||||||
|
|
||||||
// File not exists -> do not bypass
|
|
||||||
guard fileManager.fileExists(atPath: xcassetImagePath) else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Info unavailable -> do not bypass
|
|
||||||
let taskWidth = Shell.shell("identify", "-format", "%w", xcassetImagePath)
|
|
||||||
let taskHeight = Shell.shell("identify", "-format", "%h", xcassetImagePath)
|
|
||||||
guard taskWidth.terminationStatus == 0,
|
|
||||||
taskHeight.terminationStatus == 0 else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentWidth = Int(taskWidth.output ?? "-1") ?? -1
|
|
||||||
let currentheight = Int(taskHeight.output ?? "-1") ?? -1
|
|
||||||
|
|
||||||
// Info unavailable -> do not bypass
|
|
||||||
guard currentWidth > 0 && currentheight > 0 else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check width and height
|
|
||||||
if image.width != -1 && currentWidth == image.width {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if image.height != -1 && currentheight == image.height {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return GeneratorChecker.isFile(inputImagePath, moreRecenThan: xcassetImagePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Imagium.swift
|
// Images.swift
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Created by Thibaut Schmitt on 24/01/2022.
|
// Created by Thibaut Schmitt on 24/01/2022.
|
||||||
@ -9,7 +9,7 @@ import ToolCore
|
|||||||
import Foundation
|
import Foundation
|
||||||
import ArgumentParser
|
import ArgumentParser
|
||||||
|
|
||||||
struct Imagium: ParsableCommand {
|
struct Images: ParsableCommand {
|
||||||
|
|
||||||
// MARK: - CommandConfiguration
|
// MARK: - CommandConfiguration
|
||||||
|
|
||||||
@ -20,27 +20,19 @@ struct Imagium: ParsableCommand {
|
|||||||
|
|
||||||
// MARK: - Static
|
// MARK: - Static
|
||||||
|
|
||||||
static let toolName = "Imagium"
|
static let toolName = "Images"
|
||||||
static let defaultExtensionName = "UIImage"
|
static let defaultExtensionName = "UIImage"
|
||||||
|
static let defaultExtensionNameSUI = "Image"
|
||||||
// MARK: - Properties
|
|
||||||
|
|
||||||
var extensionFileName: String { "\(options.extensionName)+\(options.extensionSuffix).swift" }
|
|
||||||
var extensionFilePath: String { "\(options.extensionOutputPath)/\(extensionFileName)" }
|
|
||||||
var inputFilenameWithoutExt: String {
|
|
||||||
URL(fileURLWithPath: options.inputFile)
|
|
||||||
.deletingPathExtension()
|
|
||||||
.lastPathComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Command Options
|
// MARK: - Command Options
|
||||||
|
|
||||||
@OptionGroup var options: ImagiumOptions
|
@OptionGroup var options: ImagesOptions
|
||||||
|
|
||||||
// MARK: - Run
|
// MARK: - Run
|
||||||
|
|
||||||
mutating func run() {
|
mutating func run() {
|
||||||
print("[\(Self.toolName)] Starting images generation")
|
print("[\(Self.toolName)] Starting images generation")
|
||||||
|
print("[\(Self.toolName)] Will use inputFile \(options.inputFile) to generate images in xcassets \(options.xcassetsPath)")
|
||||||
|
|
||||||
// Check requirements
|
// Check requirements
|
||||||
guard checkRequirements() else { return }
|
guard checkRequirements() else { return }
|
||||||
@ -54,18 +46,26 @@ struct Imagium: ParsableCommand {
|
|||||||
let inputFolder = URL(fileURLWithPath: options.inputFile)
|
let inputFolder = URL(fileURLWithPath: options.inputFile)
|
||||||
.deletingLastPathComponent()
|
.deletingLastPathComponent()
|
||||||
.relativePath
|
.relativePath
|
||||||
|
|
||||||
let xcassetsGenerator = XcassetsGenerator(forceGeneration: options.forceExecutionAndGeneration)
|
let xcassetsGenerator = XcassetsGenerator(forceGeneration: options.forceExecutionAndGeneration)
|
||||||
xcassetsGenerator.generateXcassets(inputPath: inputFolder,
|
xcassetsGenerator.generateXcassets(inputPath: inputFolder,
|
||||||
imagesToGenerate: imagesToGenerate,
|
imagesToGenerate: imagesToGenerate,
|
||||||
xcassetsPath: options.xcassetsPath)
|
xcassetsPath: options.xcassetsPath)
|
||||||
|
|
||||||
// Generate extension
|
// Generate extension
|
||||||
ImageExtensionGenerator.writeStringsFiles(images: imagesToGenerate,
|
ImageExtensionGenerator.generateExtensionFile(images: imagesToGenerate,
|
||||||
staticVar: options.extensionName == Self.defaultExtensionName,
|
staticVar: options.staticMembers,
|
||||||
inputFilename: inputFilenameWithoutExt,
|
inputFilename: options.inputFilenameWithoutExt,
|
||||||
extensionName: options.extensionName,
|
extensionName: options.extensionName,
|
||||||
extensionFilePath: extensionFilePath)
|
extensionFilePath: options.extensionFilePath,
|
||||||
|
isSwiftUI: false)
|
||||||
|
|
||||||
|
ImageExtensionGenerator.generateExtensionFile(images: imagesToGenerate,
|
||||||
|
staticVar: options.staticMembers,
|
||||||
|
inputFilename: options.inputFilenameWithoutExt,
|
||||||
|
extensionName: options.extensionNameSwiftUI,
|
||||||
|
extensionFilePath: options.extensionFilePathSwiftUI,
|
||||||
|
isSwiftUI: true)
|
||||||
|
|
||||||
print("[\(Self.toolName)] Images generated")
|
print("[\(Self.toolName)] Images generated")
|
||||||
}
|
}
|
||||||
@ -81,16 +81,25 @@ struct Imagium: ParsableCommand {
|
|||||||
|
|
||||||
// Input file
|
// Input file
|
||||||
guard fileManager.fileExists(atPath: options.inputFile) else {
|
guard fileManager.fileExists(atPath: options.inputFile) else {
|
||||||
let error = ImagiumError.fileNotExists(options.inputFile)
|
let error = ImagesError.fileNotExists(options.inputFile)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Imagium.exit(withError: error)
|
Images.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RSVG-Converter
|
// RSVG-Converter
|
||||||
_ = Imagium.getSvgConverterPath()
|
_ = Images.getSvgConverterPath()
|
||||||
|
|
||||||
|
// Extension for UIKit and SwiftUI should have different name
|
||||||
|
guard options.extensionName != options.extensionNameSwiftUI else {
|
||||||
|
let error = ImagesError.extensionNamesCollision(options.extensionName)
|
||||||
|
print(error.description)
|
||||||
|
Images.exit(withError: error)
|
||||||
|
}
|
||||||
|
|
||||||
// Check if needed to regenerate
|
// Check if needed to regenerate
|
||||||
guard GeneratorChecker.shouldGenerate(force: options.forceExecution, inputFilePath: options.inputFile, extensionFilePath: extensionFilePath) else {
|
guard GeneratorChecker.shouldGenerate(force: options.forceExecution,
|
||||||
|
inputFilePath: options.inputFile,
|
||||||
|
extensionFilePath: options.extensionFilePath) else {
|
||||||
print("[\(Self.toolName)] Images are already up to date :) ")
|
print("[\(Self.toolName)] Images are already up to date :) ")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -102,15 +111,13 @@ struct Imagium: ParsableCommand {
|
|||||||
|
|
||||||
@discardableResult
|
@discardableResult
|
||||||
static func getSvgConverterPath() -> String {
|
static func getSvgConverterPath() -> String {
|
||||||
let taskSvgConverter = Shell.shell("which", "rsvg-convert")
|
let taskSvgConverter = Shell.shell(["which", "rsvg-convert"])
|
||||||
if taskSvgConverter.terminationStatus == 0 {
|
if taskSvgConverter.terminationStatus == 0 {
|
||||||
return taskSvgConverter.output!.removeCharacters(from: CharacterSet.whitespacesAndNewlines)
|
return taskSvgConverter.output!.removeCharacters(from: CharacterSet.whitespacesAndNewlines)
|
||||||
}
|
}
|
||||||
|
|
||||||
let error = ImagiumError.rsvgConvertNotFound
|
let error = ImagesError.rsvgConvertNotFound
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Imagium.exit(withError: error)
|
Images.exit(withError: error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Imagium.main()
|
|
51
Sources/ResgenSwift/Images/ImagesError.swift
Normal file
51
Sources/ResgenSwift/Images/ImagesError.swift
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// ImagesError.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 24/01/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum ImagesError: Error {
|
||||||
|
case extensionNamesCollision(String)
|
||||||
|
case inputFolderNotFound(String)
|
||||||
|
case fileNotExists(String)
|
||||||
|
case unknownImageExtension(String)
|
||||||
|
case getFileAttributed(String, String)
|
||||||
|
case rsvgConvertNotFound
|
||||||
|
case writeFile(String, String)
|
||||||
|
case createAssetFolder(String)
|
||||||
|
case unknown(String)
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .extensionNamesCollision(let extensionName):
|
||||||
|
return "error: [\(Fonts.toolName)] Error on extension names, extension name and SwiftUI extension name should be different (\(extensionName) is used on both)"
|
||||||
|
|
||||||
|
case .inputFolderNotFound(let inputFolder):
|
||||||
|
return "error: [\(Images.toolName)] Input folder not found: \(inputFolder)"
|
||||||
|
|
||||||
|
case .fileNotExists(let filename):
|
||||||
|
return "error: [\(Images.toolName)] File \(filename) does not exists"
|
||||||
|
|
||||||
|
case .unknownImageExtension(let filename):
|
||||||
|
return "error: [\(Images.toolName)] File \(filename) have an unhandled file extension. Cannot generate image."
|
||||||
|
|
||||||
|
case .getFileAttributed(let filename, let errorDescription):
|
||||||
|
return "error: [\(Images.toolName)] Getting file attributes of \(filename) failed with error: \(errorDescription)"
|
||||||
|
|
||||||
|
case .rsvgConvertNotFound:
|
||||||
|
return "error: [\(Images.toolName)] Can't find rsvg-convert (can be installed with 'brew remove imagemagick && brew install imagemagick --with-librsvg')"
|
||||||
|
|
||||||
|
case .writeFile(let subErrorDescription, let filename):
|
||||||
|
return "error: [\(Images.toolName)] An error occured while writing content to \(filename): \(subErrorDescription)"
|
||||||
|
|
||||||
|
case .createAssetFolder(let folder):
|
||||||
|
return "error: [\(Colors.toolName)] An error occured while creating folder `\(folder)`"
|
||||||
|
|
||||||
|
case .unknown(let errorDescription):
|
||||||
|
return "error: [\(Images.toolName)] Unknown error: \(errorDescription)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
77
Sources/ResgenSwift/Images/ImagesOptions.swift
Normal file
77
Sources/ResgenSwift/Images/ImagesOptions.swift
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
//
|
||||||
|
// ImagiumOptions.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 24/01/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ArgumentParser
|
||||||
|
|
||||||
|
struct ImagesOptions: ParsableArguments {
|
||||||
|
@Flag(name: .customShort("f"), help: "Should force script execution")
|
||||||
|
var forceExecution = false
|
||||||
|
|
||||||
|
@Flag(name: .customShort("F"), help: "Regenerate all images")
|
||||||
|
var forceExecutionAndGeneration = false
|
||||||
|
|
||||||
|
@Argument(help: "Input files where strings ared defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||||
|
var inputFile: String
|
||||||
|
|
||||||
|
@Option(help: "Xcassets path where to generate images.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||||
|
var xcassetsPath: String
|
||||||
|
|
||||||
|
@Option(help: "Path where to generate the extension.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||||
|
var extensionOutputPath: String
|
||||||
|
|
||||||
|
@Option(help: "Tell if it will generate static properties or not")
|
||||||
|
var staticMembers: Bool = false
|
||||||
|
|
||||||
|
@Option(help: "Extension name. If not specified, it will generate an UIImage extension.")
|
||||||
|
var extensionName: String = Images.defaultExtensionName
|
||||||
|
|
||||||
|
@Option(help: "Extension name. If not specified, it will generate an Image extension.")
|
||||||
|
var extensionNameSwiftUI: String = Images.defaultExtensionNameSUI
|
||||||
|
|
||||||
|
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+Image{extensionSuffix}.swift")
|
||||||
|
var extensionSuffix: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Computed var
|
||||||
|
|
||||||
|
extension ImagesOptions {
|
||||||
|
|
||||||
|
// MARK: - UIKit
|
||||||
|
|
||||||
|
var extensionFileName: String {
|
||||||
|
if let extensionSuffix = extensionSuffix {
|
||||||
|
return "\(extensionName)+\(extensionSuffix).swift"
|
||||||
|
}
|
||||||
|
return "\(extensionName).swift"
|
||||||
|
}
|
||||||
|
|
||||||
|
var extensionFilePath: String {
|
||||||
|
"\(extensionOutputPath)/\(extensionFileName)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - SwiftUI
|
||||||
|
|
||||||
|
var extensionFileNameSwiftUI: String {
|
||||||
|
if let extensionSuffix = extensionSuffix {
|
||||||
|
return "\(extensionNameSwiftUI)+\(extensionSuffix).swift"
|
||||||
|
}
|
||||||
|
return "\(extensionNameSwiftUI).swift"
|
||||||
|
}
|
||||||
|
|
||||||
|
var extensionFilePathSwiftUI: String {
|
||||||
|
"\(extensionOutputPath)/\(extensionFileNameSwiftUI)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: -
|
||||||
|
|
||||||
|
var inputFilenameWithoutExt: String {
|
||||||
|
URL(fileURLWithPath: inputFile)
|
||||||
|
.deletingPathExtension()
|
||||||
|
.lastPathComponent
|
||||||
|
}
|
||||||
|
}
|
@ -72,17 +72,16 @@ struct ParsedImage {
|
|||||||
|
|
||||||
// MARK: - Extension property
|
// MARK: - Extension property
|
||||||
|
|
||||||
func getImageProperty() -> String {
|
func getImageProperty(isStatic: Bool, isSwiftUI: Bool) -> String {
|
||||||
"""
|
if isSwiftUI {
|
||||||
var \(name): UIImage {
|
return """
|
||||||
UIImage(named: "\(name)")!
|
\(isStatic ? "static ": "")var \(name): Image {
|
||||||
}
|
Image("\(name)")
|
||||||
"""
|
}
|
||||||
}
|
"""
|
||||||
|
}
|
||||||
func getStaticImageProperty() -> String {
|
return """
|
||||||
"""
|
\(isStatic ? "static ": "")var \(name): UIImage {
|
||||||
static var \(name): UIImage {
|
|
||||||
UIImage(named: "\(name)")!
|
UIImage(named: "\(name)")!
|
||||||
}
|
}
|
||||||
"""
|
"""
|
@ -13,10 +13,13 @@ class ImageFileParser {
|
|||||||
let inputFileContent = try! String(contentsOfFile: inputFile, encoding: .utf8)
|
let inputFileContent = try! String(contentsOfFile: inputFile, encoding: .utf8)
|
||||||
let stringsByLines = inputFileContent.components(separatedBy: .newlines)
|
let stringsByLines = inputFileContent.components(separatedBy: .newlines)
|
||||||
|
|
||||||
|
return Self.parseLines(stringsByLines, platform: platform)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func parseLines(_ lines: [String], platform: PlatormTag) -> [ParsedImage] {
|
||||||
var imagesToGenerate = [ParsedImage]()
|
var imagesToGenerate = [ParsedImage]()
|
||||||
|
|
||||||
// Parse file
|
lines.forEach {
|
||||||
stringsByLines.forEach {
|
|
||||||
guard $0.removeLeadingTrailingWhitespace().isEmpty == false, $0.first != "#" else {
|
guard $0.removeLeadingTrailingWhitespace().isEmpty == false, $0.first != "#" else {
|
||||||
return
|
return
|
||||||
}
|
}
|
210
Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift
Normal file
210
Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
//
|
||||||
|
// StringsFileGenerator.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 04/01/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ToolCore
|
||||||
|
|
||||||
|
class StringsFileGenerator {
|
||||||
|
|
||||||
|
// MARK: - Strings Files
|
||||||
|
|
||||||
|
static func writeStringsFiles(sections: [Section],
|
||||||
|
langs: [String],
|
||||||
|
defaultLang: String,
|
||||||
|
tags: [String],
|
||||||
|
outputPath: String,
|
||||||
|
inputFilenameWithoutExt: String) {
|
||||||
|
var stringsFilesContent = [String: String]()
|
||||||
|
for lang in langs {
|
||||||
|
stringsFilesContent[lang] = Self.generateStringsFileContent(lang: lang,
|
||||||
|
defaultLang: defaultLang,
|
||||||
|
tags: tags,
|
||||||
|
sections: sections)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write strings file content
|
||||||
|
langs.forEach { lang in
|
||||||
|
guard let fileContent = stringsFilesContent[lang] else { return }
|
||||||
|
|
||||||
|
let stringsFilePath = "\(outputPath)/\(lang).lproj/\(inputFilenameWithoutExt).strings"
|
||||||
|
let stringsFilePathURL = URL(fileURLWithPath: stringsFilePath)
|
||||||
|
do {
|
||||||
|
try fileContent.write(to: stringsFilePathURL, atomically: false, encoding: .utf8)
|
||||||
|
} catch (let error) {
|
||||||
|
let error = StringiumError.writeFile(error.localizedDescription, stringsFilePath)
|
||||||
|
print(error.description)
|
||||||
|
Stringium.exit(withError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func generateStringsFileContent(lang: String,
|
||||||
|
defaultLang: String,
|
||||||
|
tags inputTags: [String],
|
||||||
|
sections: [Section]) -> String {
|
||||||
|
var stringsFileContent = """
|
||||||
|
/**
|
||||||
|
* Apple Strings File
|
||||||
|
* Generated by ResgenSwift \(ResgenSwiftVersion)
|
||||||
|
* Language: \(lang)
|
||||||
|
*/\n
|
||||||
|
"""
|
||||||
|
|
||||||
|
sections.forEach { section in
|
||||||
|
// Check that at least one string will be generated
|
||||||
|
guard section.hasOneOrMoreMatchingTags(tags: inputTags) else {
|
||||||
|
return // Go to next section
|
||||||
|
}
|
||||||
|
|
||||||
|
stringsFileContent += "\n/********** \(section.name) **********/\n\n"
|
||||||
|
section.definitions.forEach { definition in
|
||||||
|
var skipDefinition = false // Set to true if not matching tag
|
||||||
|
let translationOpt: String? = {
|
||||||
|
// If no matching tag => skip
|
||||||
|
if definition.hasOneOrMoreMatchingTags(inputTags: inputTags) == false {
|
||||||
|
skipDefinition = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If tags contains `noTranslationTag` => get default lang
|
||||||
|
if definition.tags.contains(Stringium.noTranslationTag) {
|
||||||
|
return definition.translations[defaultLang]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else: get specific lang
|
||||||
|
return definition.translations[lang]
|
||||||
|
}()
|
||||||
|
|
||||||
|
if let translation = translationOpt {
|
||||||
|
stringsFileContent += "\"\(definition.name)\" = \"\(translation)\";\n\n"
|
||||||
|
} else if skipDefinition == false {
|
||||||
|
let error = StringiumError.langNotDefined(lang, definition.name, definition.reference != nil)
|
||||||
|
print(error.description)
|
||||||
|
Stringium.exit(withError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringsFileContent
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Extension file
|
||||||
|
|
||||||
|
static func writeExtensionFiles(sections: [Section],
|
||||||
|
defaultLang lang: String,
|
||||||
|
tags: [String],
|
||||||
|
staticVar: Bool,
|
||||||
|
inputFilename: String,
|
||||||
|
extensionName: String,
|
||||||
|
extensionFilePath: String,
|
||||||
|
extensionSuffix: String) {
|
||||||
|
// Get extension content
|
||||||
|
let extensionFileContent = Self.getExtensionContent(sections: sections,
|
||||||
|
defaultLang: lang,
|
||||||
|
tags: tags,
|
||||||
|
staticVar: staticVar,
|
||||||
|
inputFilename: inputFilename,
|
||||||
|
extensionName: extensionName,
|
||||||
|
extensionSuffix: extensionSuffix)
|
||||||
|
|
||||||
|
// Write content
|
||||||
|
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
|
||||||
|
do {
|
||||||
|
try extensionFileContent.write(to: extensionFilePathURL, atomically: false, encoding: .utf8)
|
||||||
|
} catch (let error) {
|
||||||
|
let error = StringiumError.writeFile(extensionFilePath, error.localizedDescription)
|
||||||
|
print(error.description)
|
||||||
|
Stringium.exit(withError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Extension content
|
||||||
|
|
||||||
|
static func getExtensionContent(sections: [Section],
|
||||||
|
defaultLang lang: String,
|
||||||
|
tags: [String],
|
||||||
|
staticVar: Bool,
|
||||||
|
inputFilename: String,
|
||||||
|
extensionName: String,
|
||||||
|
extensionSuffix: String) -> String {
|
||||||
|
[
|
||||||
|
Self.getHeader(stringsFilename: inputFilename, extensionClassname: extensionName),
|
||||||
|
Self.getEnumKey(sections: sections, tags: tags, extensionSuffix: extensionSuffix),
|
||||||
|
Self.getProperties(sections: sections, defaultLang: lang, tags: tags, staticVar: staticVar),
|
||||||
|
Self.getFooter()
|
||||||
|
]
|
||||||
|
.joined(separator: "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Extension part
|
||||||
|
|
||||||
|
private static func getHeader(stringsFilename: String, extensionClassname: String) -> String {
|
||||||
|
"""
|
||||||
|
// Generated by ResgenSwift.Strings.\(Stringium.toolName) \(ResgenSwiftVersion)
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
fileprivate let kStringsFileName = "\(stringsFilename)"
|
||||||
|
|
||||||
|
extension \(extensionClassname) {
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getEnumKey(sections: [Section], tags: [String], extensionSuffix: String) -> String {
|
||||||
|
var enumDefinition = "\n enum Key\(extensionSuffix.uppercasedFirst()): String {\n"
|
||||||
|
|
||||||
|
sections.forEach { section in
|
||||||
|
// Check that at least one string will be generated
|
||||||
|
guard section.hasOneOrMoreMatchingTags(tags: tags) else {
|
||||||
|
return // Go to next section
|
||||||
|
}
|
||||||
|
|
||||||
|
section.definitions.forEach { definition in
|
||||||
|
guard definition.hasOneOrMoreMatchingTags(inputTags: tags) == true else {
|
||||||
|
return // Go to next definition
|
||||||
|
}
|
||||||
|
debugPrint("Found definition")
|
||||||
|
enumDefinition += " case \(definition.name) = \"\(definition.name)\"\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enumDefinition += " }"
|
||||||
|
|
||||||
|
return enumDefinition
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getProperties(sections: [Section], defaultLang lang: String, tags: [String], staticVar: Bool) -> String {
|
||||||
|
sections.compactMap { section in
|
||||||
|
// Check that at least one string will be generated
|
||||||
|
guard section.hasOneOrMoreMatchingTags(tags: tags) else {
|
||||||
|
return nil // Go to next section
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = "\n // MARK: - \(section.name)\n"
|
||||||
|
res += section.definitions.compactMap { definition in
|
||||||
|
guard definition.hasOneOrMoreMatchingTags(inputTags: tags) == true else {
|
||||||
|
return nil // Go to next definition
|
||||||
|
}
|
||||||
|
|
||||||
|
if staticVar {
|
||||||
|
return "\n\(definition.getNSLocalizedStringStaticProperty(forLang: lang))"
|
||||||
|
}
|
||||||
|
return "\n\(definition.getNSLocalizedStringProperty(forLang: lang))"
|
||||||
|
}
|
||||||
|
.joined(separator: "\n")
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
.joined(separator: "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getFooter() -> String {
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
86
Sources/ResgenSwift/Strings/Generator/TagsGenerator.swift
Normal file
86
Sources/ResgenSwift/Strings/Generator/TagsGenerator.swift
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
//
|
||||||
|
// TagsGenerator.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 10/01/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ToolCore
|
||||||
|
import CoreVideo
|
||||||
|
|
||||||
|
class TagsGenerator {
|
||||||
|
static func writeExtensionFiles(sections: [Section], lang: String, tags: [String], staticVar: Bool, extensionName: String, extensionFilePath: String) {
|
||||||
|
// Get extension content
|
||||||
|
let extensionFileContent = Self.getExtensionContent(sections: sections,
|
||||||
|
lang: lang,
|
||||||
|
tags: tags,
|
||||||
|
staticVar: staticVar,
|
||||||
|
extensionName: extensionName)
|
||||||
|
|
||||||
|
// Write content
|
||||||
|
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
|
||||||
|
do {
|
||||||
|
try extensionFileContent.write(to: extensionFilePathURL, atomically: false, encoding: .utf8)
|
||||||
|
} catch (let error) {
|
||||||
|
let error = StringiumError.writeFile(extensionFilePath, error.localizedDescription)
|
||||||
|
print(error.description)
|
||||||
|
Stringium.exit(withError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Extension content
|
||||||
|
|
||||||
|
static func getExtensionContent(sections: [Section], lang: String, tags: [String], staticVar: Bool, extensionName: String) -> String {
|
||||||
|
[
|
||||||
|
Self.getHeader(extensionClassname: extensionName, staticVar: staticVar),
|
||||||
|
Self.getProperties(sections: sections, lang: lang, tags: tags, staticVar: staticVar),
|
||||||
|
Self.getFooter()
|
||||||
|
]
|
||||||
|
.joined(separator: "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Extension part
|
||||||
|
|
||||||
|
private static func getHeader(extensionClassname: String, staticVar: Bool) -> String {
|
||||||
|
"""
|
||||||
|
// Generated by ResgenSwift.Strings.\(Tags.toolName) \(ResgenSwiftVersion)
|
||||||
|
|
||||||
|
\(staticVar ? "typelias Tags = String\n\n" : "")import UIKit
|
||||||
|
|
||||||
|
extension \(extensionClassname) {
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getProperties(sections: [Section], lang: String, tags: [String], staticVar: Bool) -> String {
|
||||||
|
sections
|
||||||
|
.compactMap { section in
|
||||||
|
// Check that at least one string will be generated
|
||||||
|
guard section.hasOneOrMoreMatchingTags(tags: tags) else {
|
||||||
|
return nil// Go to next section
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = "\n // MARK: - \(section.name)"
|
||||||
|
section.definitions.forEach { definition in
|
||||||
|
guard definition.hasOneOrMoreMatchingTags(inputTags: tags) == true else {
|
||||||
|
return // Go to next definition
|
||||||
|
}
|
||||||
|
|
||||||
|
if staticVar {
|
||||||
|
res += "\n\n\(definition.getStaticProperty(forLang: lang))"
|
||||||
|
} else {
|
||||||
|
res += "\n\n\(definition.getProperty(forLang: lang))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
.joined(separator: "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getFooter() -> String {
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
@ -53,7 +53,6 @@ class Definition {
|
|||||||
guard let match = match else { return }
|
guard let match = match else { return }
|
||||||
|
|
||||||
if let range = Range(match.range, in: input), let last = input[range].last {
|
if let range = Range(match.range, in: input), let last = input[range].last {
|
||||||
debugPrint("Found: \(input[range])")
|
|
||||||
switch last {
|
switch last {
|
||||||
case "d", "u":
|
case "d", "u":
|
||||||
methodsParameters.append("Int")
|
methodsParameters.append("Int")
|
||||||
@ -110,7 +109,7 @@ class Definition {
|
|||||||
func getNSLocalizedStringProperty(forLang lang: String) -> String {
|
func getNSLocalizedStringProperty(forLang lang: String) -> String {
|
||||||
guard let translation = translations[lang] else {
|
guard let translation = translations[lang] else {
|
||||||
let error = StringiumError.langNotDefined(lang, name, reference != nil)
|
let error = StringiumError.langNotDefined(lang, name, reference != nil)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Stringium.exit(withError: error)
|
Stringium.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +132,7 @@ class Definition {
|
|||||||
func getNSLocalizedStringStaticProperty(forLang lang: String) -> String {
|
func getNSLocalizedStringStaticProperty(forLang lang: String) -> String {
|
||||||
guard let translation = translations[lang] else {
|
guard let translation = translations[lang] else {
|
||||||
let error = StringiumError.langNotDefined(lang, name, reference != nil)
|
let error = StringiumError.langNotDefined(lang, name, reference != nil)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Stringium.exit(withError: error)
|
Stringium.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +157,7 @@ class Definition {
|
|||||||
func getProperty(forLang lang: String) -> String {
|
func getProperty(forLang lang: String) -> String {
|
||||||
guard let translation = translations[lang] else {
|
guard let translation = translations[lang] else {
|
||||||
let error = StringiumError.langNotDefined(lang, name, reference != nil)
|
let error = StringiumError.langNotDefined(lang, name, reference != nil)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Stringium.exit(withError: error)
|
Stringium.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +173,7 @@ class Definition {
|
|||||||
func getStaticProperty(forLang lang: String) -> String {
|
func getStaticProperty(forLang lang: String) -> String {
|
||||||
guard let translation = translations[lang] else {
|
guard let translation = translations[lang] else {
|
||||||
let error = StringiumError.langNotDefined(lang, name, reference != nil)
|
let error = StringiumError.langNotDefined(lang, name, reference != nil)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Stringium.exit(withError: error)
|
Stringium.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +84,7 @@ class TwineFileParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if invalidDefinitionNames.count > 0 {
|
if invalidDefinitionNames.count > 0 {
|
||||||
print(" warning:[\(Stringium.toolName)] Found \(invalidDefinitionNames.count) definition (\(invalidDefinitionNames.joined(separator: ", "))")
|
print("warning: [\(Stringium.toolName)] Found \(invalidDefinitionNames.count) definition (\(invalidDefinitionNames.joined(separator: ", "))")
|
||||||
}
|
}
|
||||||
|
|
||||||
return sections
|
return sections
|
@ -24,37 +24,15 @@ struct Stringium: ParsableCommand {
|
|||||||
static let defaultExtensionName = "String"
|
static let defaultExtensionName = "String"
|
||||||
static let noTranslationTag: String = "notranslation"
|
static let noTranslationTag: String = "notranslation"
|
||||||
|
|
||||||
// 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 inputFilenameWithoutExt: String {
|
|
||||||
URL(fileURLWithPath: options.inputFile)
|
|
||||||
.deletingPathExtension()
|
|
||||||
.lastPathComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
var generateStaticVariable: Bool {
|
|
||||||
options.extensionName == Self.defaultExtensionName
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Command options
|
// MARK: - Command options
|
||||||
|
|
||||||
// The `@OptionGroup` attribute includes the flags, options, and
|
|
||||||
// arguments defined by another `ParsableArguments` type.
|
|
||||||
@OptionGroup var options: StringiumOptions
|
@OptionGroup var options: StringiumOptions
|
||||||
|
|
||||||
// MARK: - Run
|
// MARK: - Run
|
||||||
|
|
||||||
mutating func run() {
|
mutating func run() {
|
||||||
print("[\(Self.toolName)] Starting strings generation")
|
print("[\(Self.toolName)] Starting strings generation")
|
||||||
|
print("[\(Self.toolName)] Will use inputFile \(options.inputFile) to generate strings for \(options.langs) (default lang: \(options.defaultLang)")
|
||||||
|
|
||||||
// Check requirements
|
// Check requirements
|
||||||
guard checkRequirements() else { return }
|
guard checkRequirements() else { return }
|
||||||
@ -70,16 +48,17 @@ struct Stringium: ParsableCommand {
|
|||||||
defaultLang: options.defaultLang,
|
defaultLang: options.defaultLang,
|
||||||
tags: options.tags,
|
tags: options.tags,
|
||||||
outputPath: options.stringsFileOutputPath,
|
outputPath: options.stringsFileOutputPath,
|
||||||
inputFilenameWithoutExt: inputFilenameWithoutExt)
|
inputFilenameWithoutExt: options.inputFilenameWithoutExt)
|
||||||
|
|
||||||
// Generate extension
|
// Generate extension
|
||||||
StringsFileGenerator.writeExtensionFiles(sections: sections,
|
StringsFileGenerator.writeExtensionFiles(sections: sections,
|
||||||
defaultLang: options.defaultLang,
|
defaultLang: options.defaultLang,
|
||||||
tags: options.tags,
|
tags: options.tags,
|
||||||
staticVar: generateStaticVariable,
|
staticVar: options.staticMembers,
|
||||||
inputFilename: inputFilenameWithoutExt,
|
inputFilename: options.inputFilenameWithoutExt,
|
||||||
extensionName: options.extensionName,
|
extensionName: options.extensionName,
|
||||||
extensionFilePath: extensionFilePath)
|
extensionFilePath: options.extensionFilePath,
|
||||||
|
extensionSuffix: options.extensionSuffix)
|
||||||
|
|
||||||
print("[\(Self.toolName)] Strings generated")
|
print("[\(Self.toolName)] Strings generated")
|
||||||
}
|
}
|
||||||
@ -92,25 +71,27 @@ struct Stringium: ParsableCommand {
|
|||||||
// Input file
|
// Input file
|
||||||
guard fileManager.fileExists(atPath: options.inputFile) else {
|
guard fileManager.fileExists(atPath: options.inputFile) else {
|
||||||
let error = StringiumError.fileNotExists(options.inputFile)
|
let error = StringiumError.fileNotExists(options.inputFile)
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Stringium.exit(withError: error)
|
Stringium.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Langs
|
// Langs
|
||||||
guard options.langs.isEmpty == false else {
|
guard options.langs.isEmpty == false else {
|
||||||
let error = StringiumError.langsListEmpty
|
let error = StringiumError.langsListEmpty
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Stringium.exit(withError: error)
|
Stringium.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
guard options.langs.contains(options.defaultLang) else {
|
guard options.langs.contains(options.defaultLang) else {
|
||||||
let error = StringiumError.defaultLangsNotInLangs
|
let error = StringiumError.defaultLangsNotInLangs
|
||||||
print(error.localizedDescription)
|
print(error.description)
|
||||||
Stringium.exit(withError: error)
|
Stringium.exit(withError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if needed to regenerate
|
// Check if needed to regenerate
|
||||||
guard GeneratorChecker.shouldGenerate(force: options.forceGeneration, inputFilePath: options.inputFile, extensionFilePath: extensionFilePath) else {
|
guard GeneratorChecker.shouldGenerate(force: options.forceGeneration,
|
||||||
|
inputFilePath: options.inputFile,
|
||||||
|
extensionFilePath: options.extensionFilePath) else {
|
||||||
print("[\(Self.toolName)] Strings are already up to date :) ")
|
print("[\(Self.toolName)] Strings are already up to date :) ")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user