27 Commits

Author SHA1 Message Date
09556ba6e0 [DEVTOOLS-186] Exporter les images de resgen en svg
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
Reviewed-on: #12
Reviewed-by: Thibaut Schmitt <t.schmitt@openium.fr>
2024-07-17 15:18:13 +02:00
dea57dc1e2 Maj du readme
Some checks failed
gitea-openium/resgen.swift/pipeline/pr-master There was a failure building this commit
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
2024-07-11 10:29:32 +02:00
07575bd2bf DEVTOOLS-195 Ne pas générer les svg en template par défaut
Some checks failed
gitea-openium/resgen.swift/pipeline/pr-master There was a failure building this commit
2024-07-11 10:08:47 +02:00
8686ae974c Suppression des anciens assets si svg
Some checks failed
gitea-openium/resgen.swift/pipeline/pr-master There was a failure building this commit
2024-06-21 14:54:20 +02:00
be4c561ea8 DEVTOOLS-192 Resgen iOS vector
Some checks failed
gitea-openium/resgen.swift/pipeline/pr-master There was a failure building this commit
2024-06-21 09:18:51 +02:00
2357a40fff DEVTOOLS-186 Exporter les images de resgen en svg
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
gitea-openium/resgen.swift/pipeline/pr-master There was a failure building this commit
2024-04-22 12:05:24 +02:00
d4afa9c9e9 Maj du Readme suite aux devs sur le fichier string catalog
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
2024-04-22 09:48:21 +02:00
76ef0a2d59 Merge pull request 'DEVTOOLS-185 Remplacer le json en dur des images resgen' (#11) from DEVTOOLS-186/SVG_resgen into master
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
Reviewed-on: #11
Reviewed-by: Thibaut Schmitt <t.schmitt@openium.fr>
2024-04-19 17:02:26 +02:00
129eb135f1 DEVTOOLS-185 Remplacer le json en dur des images resgen
Some checks are pending
gitea-openium/resgen.swift/pipeline/pr-master Build started...
2024-04-19 17:02:00 +02:00
4ad15fcded Merge pull request 'xcstrings' (#10) from xcstrings into master
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
Reviewed-on: #10
Reviewed-by: Thibaut Schmitt <t.schmitt@openium.fr>
2024-04-19 16:59:03 +02:00
fb2ddb2227 DEVTOOLS-181 Gérer le tag noTranslation pour les xcstrings 2024-04-17 09:44:09 +02:00
27f86f5c4d Correction de l'option pour le fichier xcstrings 2024-04-15 16:51:18 +02:00
209ba49e3f Gestion des commentaires 2024-04-12 17:15:15 +02:00
ba07005b13 Fix equatable properties for arrays 2024-04-12 16:45:09 +02:00
6c3f3a8982 Correction du test testGenerateXcStringsRootObject 2024-04-12 16:25:10 +02:00
0d651b810f Première implémentation des xcstrings 2024-04-12 16:09:54 +02:00
1d7fc76340 Changed the condition for moe visibility 2024-04-11 15:49:07 +02:00
5d4e461933 Affichage du commentaire même si nil ou empty 2024-04-11 14:20:54 +02:00
55264d61ad Modification de l'affichage des commentaires
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
gitea-openium/resgen.swift/pipeline/pr-master There was a failure building this commit
2024-04-11 11:18:57 +02:00
d21ad9d1ea Update JenkinsFile Xcode version
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
2024-04-11 10:19:10 +02:00
0bd6c3c2d4 Correction des commentaires des strings
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
2024-04-11 10:16:28 +02:00
eed20367b9 fix: Edit for NSObject in Firebase
Some checks failed
gitea-openium/resgen.swift/pipeline/pr-master There was a failure building this commit
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
PixeeBox/resgen.swift/pipeline/head There was a failure building this commit
2023-12-13 11:24:21 +01:00
43b5111d79 Actualiser Sources/ResgenSwift/Analytics/Generator/AnalyticsGenerator.swift
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
2023-12-13 10:39:12 +01:00
2983093a9c Add Swiftlint 2023-12-13 10:39:12 +01:00
b4bbaa3bfd Fix Image 2023-12-13 10:39:12 +01:00
498c8fa4ae Fix Font 2023-12-13 10:39:12 +01:00
2957da6233 Fix Color 2023-12-13 10:39:12 +01:00
54 changed files with 2584 additions and 386 deletions

View File

@ -13,7 +13,7 @@
- Update plist `UIAppFonts` when generated fonts (use plistBuddy)
- New parameter: `infoPlistPaths`
- Generate SwiftUI extensions for colors, fonts and images
- New parameter: `extensionNameSwiftUI`
- New parameter: `extensionNameUIKit`
- Adding Makefile to install, unsintall and create man page.
## Fixes

2
Jenkinsfile vendored
View File

@ -1,6 +1,6 @@
library "openiumpipeline"
env.DEVELOPER_DIR="/Applications/Xcode-15.0.1.app/Contents/Developer"
env.DEVELOPER_DIR="/Applications/Xcode-15.4.0.app/Contents/Developer"
//env.SIMULATOR_DEVICE_TYPES="iPad--7th-generation-"
env.IS_PACKAGE_SWIFT=1
env.TARGETS_MACOS=1

View File

@ -1,12 +1,75 @@
{
"pins" : [
{
"identity" : "collectionconcurrencykit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/JohnSundell/CollectionConcurrencyKit.git",
"state" : {
"revision" : "b4f23e24b5a1bff301efc5e70871083ca029ff95",
"version" : "0.2.0"
}
},
{
"identity" : "cryptoswift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/krzyzanowskim/CryptoSwift.git",
"state" : {
"revision" : "c9c3df6ab812de32bae61fc0cd1bf6d45170ebf0",
"version" : "1.8.2"
}
},
{
"identity" : "sourcekitten",
"kind" : "remoteSourceControl",
"location" : "https://github.com/jpsim/SourceKitten.git",
"state" : {
"revision" : "b6dc09ee51dfb0c66e042d2328c017483a1a5d56",
"version" : "0.34.1"
}
},
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser",
"state" : {
"revision" : "9f39744e025c7d377987f30b03770805dcb0bcd1",
"version" : "1.1.4"
"revision" : "8f4d2753f0e4778c76d5f05ad16c74f707390531",
"version" : "1.2.3"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax.git",
"state" : {
"revision" : "6ad4ea24b01559dde0773e3d091f1b9e36175036",
"version" : "509.0.2"
}
},
{
"identity" : "swiftlint",
"kind" : "remoteSourceControl",
"location" : "https://github.com/realm/SwiftLint.git",
"state" : {
"revision" : "f17a4f9dfb6a6afb0408426354e4180daaf49cee",
"version" : "0.54.0"
}
},
{
"identity" : "swiftytexttable",
"kind" : "remoteSourceControl",
"location" : "https://github.com/scottrhoyt/SwiftyTextTable.git",
"state" : {
"revision" : "c6df6cf533d120716bff38f8ff9885e1ce2a4ac3",
"version" : "0.9.0"
}
},
{
"identity" : "swxmlhash",
"kind" : "remoteSourceControl",
"location" : "https://github.com/drmohundro/SWXMLHash.git",
"state" : {
"revision" : "a853604c9e9a83ad9954c7e3d2a565273982471f",
"version" : "7.0.2"
}
},
{
@ -14,8 +77,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/jpsim/Yams.git",
"state" : {
"revision" : "01835dc202670b5bb90d07f3eae41867e9ed29f6",
"version" : "5.0.1"
"revision" : "0d9ee7ea8c4ebd4a489ad7a73d5c6cad55d6fed3",
"version" : "5.0.6"
}
}
],

View File

@ -9,7 +9,8 @@ let package = Package(
dependencies: [
// 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/jpsim/Yams.git", from: "5.0.1")
.package(url: "https://github.com/jpsim/Yams.git", from: "5.0.1"),
.package(url: "https://github.com/realm/SwiftLint.git", .upToNextMajor(from: "0.54.0")),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
@ -20,7 +21,8 @@ let package = Package(
"ToolCore",
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"Yams"
]
],
plugins: [.plugin(name: "SwiftLintPlugin", package: "SwiftLint")]
),
// Helper targets

View File

@ -16,7 +16,7 @@ iOS required to use the **real name** of the font, this name can be different fr
swift run -c release ResgenSwift fonts $FORCE_FLAG "./Fonts/fonts.txt" \
--extension-output-path "./Fonts/Generated" \
--extension-name "AppFont" \
--extension-name-swift-ui "SUIAppFont" \
--extension-name-ui-kit "UIAppFont" \
--extension-suffix "GreatApp" \
--static-members true \
--info-plist-paths "./path/one/to/Info.plist ./path/two/to/Info.plist"
@ -27,8 +27,8 @@ swift run -c release ResgenSwift fonts $FORCE_FLAG "./Fonts/fonts.txt" \
1. `-f`: force generation
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
4. `--extension-name` *(optional)* : name of the class to add UIKit getters
5. `--extension-name-swift-ui` *(optional)* : name of the class to add SwiftUI getters
4. `--extension-name` *(optional)* : name of the class to add SwiftUI getters
5. `--extension-name-ui-kit` *(optional)* : name of the class to add UIKit getters
6. `--extension-suffix` *(optional)* : additional text which is added to the filename (ex: `AppFont+GreatApp.swift`)
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
@ -44,7 +44,7 @@ swift run -c release ResgenSwift colors $FORCE_FLAG "./Colors/colors.txt" \
--xcassets-path "./Colors/colors.xcassets" \
--extension-output-path "./Colors/Generated/" \
--extension-name "AppColor" \
--extension-name-swift-ui "SUIAppColor" \
--extension-name-ui-kit "UIAppColor" \
--extension-suffix "GreatApp" \
--static-members true
```
@ -55,8 +55,8 @@ swift run -c release ResgenSwift colors $FORCE_FLAG "./Colors/colors.txt" \
2. Input colors file
3. `--style` can be `all` or `light`
4. `--extension-output-path`: path where to generate generated 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
5. `--extension-name` *(optional)* : name of the class to add SwiftUI getters
6. `--extension-name-ui-kit` *(optional)* : name of the class to add UIKit 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
@ -81,7 +81,7 @@ swift run -c release ResgenSwift strings twine $FORCE_FLAG "./Twine/strings.txt"
2. Input translations file (must be Twine formatted)
3. `--langs`: langs to generate (string with space between each lang)
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
5. `--extension-output-path`: path where to generate generated extension
### Stringium (recommended)
@ -93,6 +93,7 @@ swift run -c release ResgenSwift strings stringium $FORCE_FLAG "./Strings/string
--extension-output-path "./Strings/Generated" \
--extension-name "AppString" \
--extension-suffix "GreatApp" \
--xcStrings true
--static-members true
```
@ -105,6 +106,7 @@ swift run -c release ResgenSwift strings stringium $FORCE_FLAG "./Strings/string
4. `--extension-output-path`: path where to generate generated 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. `--xcStrings`*(optional)* : generate string catalog
7. `--static-members` *(optional)*: generate static properties or not
@ -200,14 +202,14 @@ You need to put `_` + `NAME OF THE PARAMETER` + `_` in the target and which targ
## 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 ResgenSwift images $FORCE_FLAG "./Images/images.txt" \
--xcassets-path "./Images/app.xcassets" \
--extension-output-path "./Images/Generated" \
--extension-name "AppImage" \
--extension-name-swift-ui "SUIAppImage" \
--extension-name-ui-kit "UIAppImage" \
--extension-suffix "GreatApp" \
--static-members true
```
@ -218,11 +220,12 @@ swift run -c release ResgenSwift images $FORCE_FLAG "./Images/images.txt" \
2. Input images definitions file
3. `--xcassets-path`: xcasset path where to generate imagesets
4. `--extension-output-path`: path where to generate generated 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
5. `--extension-name` *(optional)* : name of the class to add SwiftUI getters
6. `--extension-name-ui-kit` *(optional)* : name of the class to add UIKit getters
6. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppImage+GreatApp.swift`)
7. `--static-members` *(optional)*: generate static properties or not
> ⚠️ Svg images will be copied in the assets and rendered as "Original", however if those images are not rendered correctly you can force the png generation by adding the key word "png" like this: id arrow_back 15 ? png
## All at once
@ -241,7 +244,7 @@ colors:
xcassetsPath: String
extensionOutputPath: String
extensionName: String?
extensionNameSwiftUI: String?
extensionNameUIKit: String?
extensionSuffix: String?
staticMembers: Bool?
@ -250,7 +253,7 @@ fonts:
inputFile: String
extensionOutputPath: String
extensionName: String?
extensionNameSwiftUI: String?
extensionNameUIKit: String?
extensionSuffix: String?
staticMembers: Bool?
infoPlistPaths: [String]
@ -261,7 +264,7 @@ images:
xcassetsPath: String
extensionOutputPath: String
extensionName: String?
extensionNameSwiftUI: String?
extensionNameUIKit: String?
extensionSuffix: String?
staticMembers: Bool?
@ -301,7 +304,7 @@ colors:
xcassetsPath: String
extensionOutputPath: String
extensionName: String?
extensionNameSwiftUI: String?
extensionNameUIKit: String?
extensionSuffix: String?
staticMembers: Bool?
-
@ -310,7 +313,7 @@ colors:
xcassetsPath: String
extensionOutputPath: String
extensionName: String?
extensionNameSwiftUI: String?
extensionNameUIKit: String?
extensionSuffix: String?
staticMembers: Bool?
...

View File

@ -81,7 +81,7 @@ class MatomoAnalyticsManager: AnalyticsManagerProtocol {
class FirebaseAnalyticsManager: AnalyticsManagerProtocol {
func logScreen(name: String, path: String) {
var parameters = [
AnalyticsParameterScreenName: name
AnalyticsParameterScreenName: name as NSObject
]
Analytics.logEvent(
@ -96,19 +96,25 @@ class FirebaseAnalyticsManager: AnalyticsManagerProtocol {
category: String,
params: [String: Any]?
) {
var parameters: [String:Any] = [
"action": action,
"category": category,
var parameters: [String:NSObject] = [
"action": action as NSObject,
"category": category as NSObject,
]
if let supplementaryParameters = params {
parameters.merge(supplementaryParameters) { (origin, new) -> Any in
return origin
for (newKey, newValue) in supplementaryParameters {
if parameters.contains(where: { (key: String, value: NSObject) in
key == newKey
}) {
continue
}
parameters[newKey] = newValue as? NSObject
}
}
Analytics.logEvent(
name,
name.replacingOccurrences(of: [" "], with: "_"),
parameters: parameters
)
}

View File

@ -5,8 +5,8 @@ FORCE_FLAG="$1"
## Font
#swift run -c release ResgenSwift fonts $FORCE_FLAG "./Fonts/sampleFontsAll.txt" \
# --extension-output-path "./Fonts/Generated" \
# --extension-name "UIFontYolo" \
# --extension-name-swift-ui "FontYolo" \
# --extension-name "FontYolo" \
# --extension-name-ui-kit "UIFontYolo" \
# --extension-suffix "GenAllScript" \
# --info-plist-paths "./Fonts/Generated/test.plist ./Fonts/Generated/test2.plist"
#
@ -17,8 +17,8 @@ FORCE_FLAG="$1"
# --style all \
# --xcassets-path "./Colors/colors.xcassets" \
# --extension-output-path "./Colors/Generated/" \
# --extension-name "UIColorYolo" \
# --extension-name-swift-ui "ColorYolo" \
# --extension-name "ColorYolo" \
# --extension-name-ui-kit "UIhkjhkColorYolo" \
# --extension-suffix "GenAllScript"
#
#echo "\n-------------------------\n"
@ -49,8 +49,8 @@ FORCE_FLAG="$1"
# --extension-output-path "./Tags/Generated" \
# --extension-name "Tags" \
# --extension-suffix "GenAllScript"
#
echo "\n-------------------------\n"
#echo "\n-------------------------\n"
# Analytics
swift run -c release ResgenSwift analytics $FORCE_FLAG "./Tags/sampleTags.yml" \
@ -59,12 +59,12 @@ swift run -c release ResgenSwift analytics $FORCE_FLAG "./Tags/sampleTags.yml" \
--extension-name "Analytics" \
--extension-suffix "GenAllScript"
echo "\n-------------------------\n"
#echo "\n-------------------------\n"
#
## Images
#swift run -c release ResgenSwift images $FORCE_FLAG "./Images/sampleImages.txt" \
# --xcassets-path "./Images/imagium.xcassets" \
# --extension-output-path "./Images/Generated" \
# --extension-name "UIImage" \
# --extension-name-swift-ui "ImageYolo" \
# --extension-name "ImageYolo" \
# --extension-name-ui-kit "UIImageYolo" \
# --extension-suffix "GenAllScript"

View File

@ -47,8 +47,8 @@ images:
inputFile: ./Images/sampleImages.txt
xcassetsPath: ./Images/imagium.xcassets
extensionOutputPath: ./Images/Generated
extensionName: UIImage
extensionNameSwiftUI: ImageYolo
extensionName: ImageYolo
extensionNameUIKit: UIImageYolo
extensionSuffix: GenAllScript
@ -61,8 +61,8 @@ colors:
style: all
xcassetsPath: ./Colors/colors.xcassets
extensionOutputPath: ./Colors/Generated/
extensionName: UIColorYolo
extensionNameSwiftUI: ColorYolo
extensionName: ColorYolo
extensionNameUIKit: UIColorYolo
extensionSuffix: GenAllScript
@ -97,7 +97,7 @@ fonts:
-
inputFile: ./Fonts/sampleFontsAll.txt
extensionOutputPath: ./Fonts/Generated
extensionName: UIFontYolo
extensionNameSwiftUI: FontYolo
extensionName: FontYolo
extensionNameUIKit: UIFontYolo
extensionSuffix: GenAllScript
infoPlistPaths: "./Fonts/Generated/test.plist ./Fonts/Generated/test2.plist"

View File

@ -18,7 +18,6 @@ struct Analytics: ParsableCommand {
version: ResgenSwiftVersion
)
// MARK: - Static
static let toolName = "Analytics"

View File

@ -32,7 +32,7 @@ class AnalyticsGenerator {
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
do {
try extensionFileContent.write(to: extensionFilePathURL, atomically: false, encoding: .utf8)
} catch (let error) {
} catch let error {
let error = AnalyticsError.writeFile(extensionFilePath, error.localizedDescription)
print(error.description)
Analytics.exit(withError: error)

View File

@ -33,7 +33,7 @@ enum FirebaseGenerator {
"""
func logScreen(name: String, path: String) {
var parameters = [
AnalyticsParameterScreenName: name
AnalyticsParameterScreenName: name as NSObject
]
Analytics.logEvent(
@ -53,19 +53,25 @@ enum FirebaseGenerator {
category: String,
params: [String: Any]?
) {
var parameters: [String:Any] = [
"action": action,
"category": category,
var parameters: [String:NSObject] = [
"action": action as NSObject,
"category": category as NSObject,
]
if let supplementaryParameters = params {
parameters.merge(supplementaryParameters) { (origin, new) -> Any in
return origin
for (newKey, newValue) in supplementaryParameters {
if parameters.contains(where: { (key: String, value: NSObject) in
key == newKey
}) {
continue
}
parameters[newKey] = newValue as? NSObject
}
}
Analytics.logEvent(
name,
name.replacingOccurrences(of: [" "], with: "_"),
parameters: parameters
)
}

View File

@ -30,7 +30,7 @@ class AnalyticsDefinition {
// MARK: - Methods
func hasOneOrMoreMatchingTags(inputTags: [String]) -> Bool {
if Set(inputTags).intersection(Set(self.tags)).isEmpty {
if Set(inputTags).isDisjoint(with: tags) {
return false
}
return true
@ -52,7 +52,7 @@ class AnalyticsDefinition {
var result: String
if type == .screen {
params = params.filter{ param in
params = params.filter { param in
!param.replaceIn.isEmpty
}
}
@ -76,7 +76,7 @@ class AnalyticsDefinition {
return result
}
private func replaceIn(){
private func replaceIn() {
for parameter in parameters {
for rep in parameter.replaceIn {
switch rep {

View File

@ -21,8 +21,8 @@ struct Colors: ParsableCommand {
// MARK: - Static
static let toolName = "Color"
static let defaultExtensionName = "UIColor"
static let defaultExtensionNameSUI = "Color"
static let defaultExtensionName = "Color"
static let defaultExtensionNameUIKit = "UIColor"
static let assetsColorsFolderName = "Colors"
// MARK: - Command options
@ -57,14 +57,14 @@ struct Colors: ParsableCommand {
staticVar: options.staticMembers,
extensionName: options.extensionName,
extensionFilePath: options.extensionFilePath,
isSwiftUI: false)
isSwiftUI: true)
// Generate extension
ColorExtensionGenerator.writeExtensionFile(colors: parsedColors,
staticVar: options.staticMembers,
extensionName: options.extensionNameSwiftUI,
extensionFilePath: options.extensionFilePathSwiftUI,
isSwiftUI: true)
extensionName: options.extensionNameUIKit,
extensionFilePath: options.extensionFilePathUIKit,
isSwiftUI: false)
print("[\(Self.toolName)] Colors generated")
}
@ -89,7 +89,7 @@ struct Colors: ParsableCommand {
}
// Extension for UIKit and SwiftUI should have different name
guard options.extensionName != options.extensionNameSwiftUI else {
guard options.extensionName != options.extensionNameUIKit else {
let error = ColorsToolError.extensionNamesCollision(options.extensionName)
print(error.description)
Colors.exit(withError: error)

View File

@ -27,11 +27,11 @@ struct ColorsToolOptions: ParsableArguments {
@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.")
@Option(help: "Extension name. If not specified, it will generate an Color 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: "SwiftUI Extension name. If not specified, it will generate an UIColor extension.")
var extensionNameUIKit: String = Colors.defaultExtensionNameUIKit
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+ColorsMyApp.swift")
var extensionSuffix: String?
@ -41,7 +41,7 @@ struct ColorsToolOptions: ParsableArguments {
extension ColorsToolOptions {
// MARK: - UIKit
// MARK: - SwiftUI
var extensionFileName: String {
if let extensionSuffix = extensionSuffix {
@ -54,16 +54,16 @@ extension ColorsToolOptions {
"\(extensionOutputPath)/\(extensionFileName)"
}
// MARK: - SwiftUI
// MARK: - UIKit
var extensionFileNameSwiftUI: String {
var extensionFileNameUIKit: String {
if let extensionSuffix = extensionSuffix {
return "\(extensionNameSwiftUI)+\(extensionSuffix).swift"
return "\(extensionNameUIKit)+\(extensionSuffix).swift"
}
return "\(extensionNameSwiftUI).swift"
return "\(extensionNameUIKit).swift"
}
var extensionFilePathSwiftUI: String {
"\(extensionOutputPath)/\(extensionFileNameSwiftUI)"
var extensionFilePathUIKit: String {
"\(extensionOutputPath)/\(extensionFileNameUIKit)"
}
}

View File

@ -30,7 +30,7 @@ struct ColorExtensionGenerator {
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
do {
try extensionContent.write(to: extensionFilePathURL, atomically: false, encoding: .utf8)
} catch (let error) {
} catch let error {
let error = ColorsToolError.writeExtension(extensionFilePath, error.localizedDescription)
print(error.description)
Colors.exit(withError: error)

View File

@ -38,7 +38,7 @@ struct ColorXcassetHelper {
let contentsJsonPathURL = URL(fileURLWithPath: contentsJsonPath)
do {
try color.contentsJSON().write(to: contentsJsonPathURL, atomically: false, encoding: .utf8)
} catch (let error) {
} catch let error {
let error = ColorsToolError.writeAsset(error.localizedDescription)
print(error.description)
Colors.exit(withError: error)

View File

@ -21,11 +21,11 @@ struct FontsOptions: ParsableArguments {
@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.")
@Option(help: "Extension name. If not specified, it will generate an Font 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 name. If not specified, it will generate an UIFont extension.")
var extensionNameUIKit: String = Fonts.defaultExtensionNameUIKit
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+FontsMyApp.swift")
var extensionSuffix: String = ""
@ -38,7 +38,7 @@ struct FontsOptions: ParsableArguments {
extension FontsOptions {
// MARK: - UIKit
// MARK: - SwiftUI
var extensionFileName: String {
if extensionSuffix.isEmpty == false {
@ -51,17 +51,17 @@ extension FontsOptions {
"\(extensionOutputPath)/\(extensionFileName)"
}
// MARK: - SwiftUI
// MARK: - UIKit
var extensionFileNameSwiftUI: String {
var extensionFileNameUIKit: String {
if extensionSuffix.isEmpty == false {
return "\(extensionNameSwiftUI)+\(extensionSuffix).swift"
return "\(extensionNameUIKit)+\(extensionSuffix).swift"
}
return "\(extensionNameSwiftUI).swift"
return "\(extensionNameUIKit).swift"
}
var extensionFilePathSwiftUI: String {
"\(extensionOutputPath)/\(extensionFileNameSwiftUI)"
var extensionFilePathUIKit: String {
"\(extensionOutputPath)/\(extensionFileNameUIKit)"
}
// MARK: -

View File

@ -21,8 +21,8 @@ struct Fonts: ParsableCommand {
// MARK: - Static
static let toolName = "Fonts"
static let defaultExtensionName = "UIFont"
static let defaultExtensionNameSUI = "Font"
static let defaultExtensionName = "Font"
static let defaultExtensionNameUIKit = "UIFont"
// MARK: - Command Options
@ -52,13 +52,13 @@ struct Fonts: ParsableCommand {
staticVar: options.staticMembers,
extensionName: options.extensionName,
extensionFilePath: options.extensionFilePath,
isSwiftUI: false)
isSwiftUI: true)
FontExtensionGenerator.writeExtensionFile(fontsNames: fontsNames,
staticVar: options.staticMembers,
extensionName: options.extensionNameSwiftUI,
extensionFilePath: options.extensionFilePathSwiftUI,
isSwiftUI: true)
extensionName: options.extensionNameUIKit,
extensionFilePath: options.extensionFilePathUIKit,
isSwiftUI: false)
print("Info.plist has been updated with:")
print("\(FontPlistGenerator.generatePlistUIAppsFontContent(for: fontsNames, infoPlistPaths: options.infoPlistPaths))")
@ -79,7 +79,7 @@ struct Fonts: ParsableCommand {
}
// Extension for UIKit and SwiftUI should have different name
guard options.extensionName != options.extensionNameSwiftUI else {
guard options.extensionName != options.extensionNameUIKit else {
let error = FontsToolError.extensionNamesCollision(options.extensionName)
print(error.description)
Fonts.exit(withError: error)

View File

@ -36,7 +36,7 @@ class FontExtensionGenerator {
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
do {
try extensionContent.write(to: extensionFilePathURL, atomically: false, encoding: .utf8)
} catch (let error) {
} catch let error {
let error = FontsToolError.writeExtension(extensionFilePath, error.localizedDescription)
print(error.description)
Fonts.exit(withError: error)

View File

@ -9,7 +9,7 @@ import Foundation
enum GenerateError: Error {
case fileNotExists(String)
case invalidConfigurationFile(String)
case invalidConfigurationFile(String, String)
case commandError([String], String)
case writeFile(String, String)
@ -18,8 +18,8 @@ enum GenerateError: Error {
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 .invalidConfigurationFile(let filename, let underneathErrorDescription):
return "error: [\(Generate.toolName)] File \(filename) is not a valid configuration file. Underneath error: \(underneathErrorDescription)"
case .commandError(let command, let terminationStatus):
let readableCommand = command

View File

@ -5,8 +5,6 @@
// Created by Thibaut Schmitt on 30/08/2022.
//
import Foundation
import Foundation
import ArgumentParser

View File

@ -30,7 +30,7 @@ struct ArchitectureGenerator {
let architectureFilePathURL = URL(fileURLWithPath: "\(filePath)/\(filename)")
do {
try architectureContent.write(to: architectureFilePathURL, atomically: false, encoding: .utf8)
} catch (let error) {
} catch let error {
let error = GenerateError.writeFile(filename, error.localizedDescription)
print(error.description)
Generate.exit(withError: error)

View File

@ -127,7 +127,7 @@ struct ColorsConfiguration: Codable, CustomDebugStringConvertible {
let xcassetsPath: String
let extensionOutputPath: String
let extensionName: String?
let extensionNameSwiftUI: String?
let extensionNameUIKit: String?
let extensionSuffix: String?
private let staticMembers: Bool?
@ -143,7 +143,7 @@ struct ColorsConfiguration: Codable, CustomDebugStringConvertible {
xcassetsPath: String,
extensionOutputPath: String,
extensionName: String?,
extensionNameSwiftUI: String?,
extensionNameUIKit: String?,
extensionSuffix: String?,
staticMembers: Bool?) {
self.inputFile = inputFile
@ -151,7 +151,7 @@ struct ColorsConfiguration: Codable, CustomDebugStringConvertible {
self.xcassetsPath = xcassetsPath
self.extensionOutputPath = extensionOutputPath
self.extensionName = extensionName
self.extensionNameSwiftUI = extensionNameSwiftUI
self.extensionNameUIKit = extensionNameUIKit
self.extensionSuffix = extensionSuffix
self.staticMembers = staticMembers
}
@ -164,7 +164,7 @@ struct ColorsConfiguration: Codable, CustomDebugStringConvertible {
- Xcassets path: \(xcassetsPath)
- Extension output path: \(extensionOutputPath)
- Extension name: \(extensionName ?? "-")
- Extension name SwiftUI: \(extensionNameSwiftUI ?? "-")
- Extension name UIKit: \(extensionNameUIKit ?? "-")
- Extension suffix: \(extensionSuffix ?? "-")
"""
}
@ -174,7 +174,7 @@ struct FontsConfiguration: Codable, CustomDebugStringConvertible {
let inputFile: String
let extensionOutputPath: String
let extensionName: String?
let extensionNameSwiftUI: String?
let extensionNameUIKit: String?
let extensionSuffix: String?
let infoPlistPaths: String?
private let staticMembers: Bool?
@ -189,14 +189,14 @@ struct FontsConfiguration: Codable, CustomDebugStringConvertible {
internal init(inputFile: String,
extensionOutputPath: String,
extensionName: String?,
extensionNameSwiftUI: String?,
extensionNameUIKit: String?,
extensionSuffix: String?,
infoPlistPaths: String?,
staticMembers: Bool?) {
self.inputFile = inputFile
self.extensionOutputPath = extensionOutputPath
self.extensionName = extensionName
self.extensionNameSwiftUI = extensionNameSwiftUI
self.extensionNameUIKit = extensionNameUIKit
self.extensionSuffix = extensionSuffix
self.infoPlistPaths = infoPlistPaths
self.staticMembers = staticMembers
@ -208,7 +208,7 @@ struct FontsConfiguration: Codable, CustomDebugStringConvertible {
- Input file: \(inputFile)
- Extension output path: \(extensionOutputPath)
- Extension name: \(extensionName ?? "-")
- Extension name SwiftUI: \(extensionNameSwiftUI ?? "-")
- Extension name UIKit: \(extensionNameUIKit ?? "-")
- Extension suffix: \(extensionSuffix ?? "-")
- InfoPlistPaths: \(infoPlistPaths ?? "-")
"""
@ -220,7 +220,7 @@ struct ImagesConfiguration: Codable, CustomDebugStringConvertible {
let xcassetsPath: String
let extensionOutputPath: String
let extensionName: String?
let extensionNameSwiftUI: String?
let extensionNameUIKit: String?
let extensionSuffix: String?
private let staticMembers: Bool?
@ -235,14 +235,14 @@ struct ImagesConfiguration: Codable, CustomDebugStringConvertible {
xcassetsPath: String,
extensionOutputPath: String,
extensionName: String?,
extensionNameSwiftUI: String?,
extensionNameUIKit: String?,
extensionSuffix: String?,
staticMembers: Bool?) {
self.inputFile = inputFile
self.xcassetsPath = xcassetsPath
self.extensionOutputPath = extensionOutputPath
self.extensionName = extensionName
self.extensionNameSwiftUI = extensionNameSwiftUI
self.extensionNameUIKit = extensionNameUIKit
self.extensionSuffix = extensionSuffix
self.staticMembers = staticMembers
}
@ -254,7 +254,7 @@ struct ImagesConfiguration: Codable, CustomDebugStringConvertible {
- Xcassets path: \(xcassetsPath)
- Extension output path: \(extensionOutputPath)
- Extension name: \(extensionName ?? "-")
- Extension name SwiftUI: \(extensionNameSwiftUI ?? "-")
- Extension name UIKit: \(extensionNameUIKit ?? "-")
- Extension suffix: \(extensionSuffix ?? "-")
"""
}
@ -269,14 +269,22 @@ struct StringsConfiguration: Codable, CustomDebugStringConvertible {
let extensionName: String?
let extensionSuffix: String?
private let staticMembers: Bool?
private let xcStrings: Bool?
var staticMembersOptions: Bool {
if let staticMembers = staticMembers {
return staticMembers
}
return false
}
var xcStringsOptions: Bool {
if let xcStrings = xcStrings {
return xcStrings
}
return false
}
internal init(inputFile: String,
outputPath: String,
langs: String,
@ -284,7 +292,8 @@ struct StringsConfiguration: Codable, CustomDebugStringConvertible {
extensionOutputPath: String,
extensionName: String?,
extensionSuffix: String?,
staticMembers: Bool?) {
staticMembers: Bool?,
xcStrings: Bool?) {
self.inputFile = inputFile
self.outputPath = outputPath
self.langs = langs
@ -293,6 +302,7 @@ struct StringsConfiguration: Codable, CustomDebugStringConvertible {
self.extensionName = extensionName
self.extensionSuffix = extensionSuffix
self.staticMembers = staticMembers
self.xcStrings = xcStrings
}
var debugDescription: String {

View File

@ -16,12 +16,15 @@ class ConfigurationFileParser {
Generate.exit(withError: error)
}
guard let configuration = try? YAMLDecoder().decode(ConfigurationFile.self, from: data) else {
let error = GenerateError.invalidConfigurationFile(configurationFile)
do {
return try YAMLDecoder().decode(ConfigurationFile.self, from: data)
} catch {
let error = GenerateError.invalidConfigurationFile(
configurationFile,
error.localizedDescription.description
)
print(error.description)
Generate.exit(withError: error)
}
return configuration
}
}

View File

@ -38,10 +38,10 @@ extension ColorsConfiguration: Runnable {
extensionName
]
}
if let extensionNameSwiftUI = extensionNameSwiftUI {
if let extensionNameUIKit = extensionNameUIKit {
args += [
"--extension-name-swift-ui",
extensionNameSwiftUI
"--extension-name-ui-kit",
extensionNameUIKit
]
}
if let extensionSuffix = extensionSuffix {

View File

@ -34,10 +34,10 @@ extension FontsConfiguration: Runnable {
extensionName
]
}
if let extensionNameSwiftUI = extensionNameSwiftUI {
if let extensionNameUIKit = extensionNameUIKit {
args += [
"--extension-name-swift-ui",
extensionNameSwiftUI
"--extension-name-ui-kit",
extensionNameUIKit
]
}

View File

@ -36,10 +36,10 @@ extension ImagesConfiguration: Runnable {
extensionName
]
}
if let extensionNameSwiftUI = extensionNameSwiftUI {
if let extensionNameUIKit = extensionNameUIKit {
args += [
"--extension-name-swift-ui",
extensionNameSwiftUI
"--extension-name-ui-kit",
extensionNameUIKit
]
}
if let extensionSuffix = extensionSuffix {

View File

@ -10,4 +10,3 @@ import Foundation
protocol Runnable {
func run(projectDirectory: String, force: Bool)
}

View File

@ -14,7 +14,7 @@ extension StringsConfiguration: Runnable {
if force {
args += ["-f"]
}
args += [
inputFile.prependIfRelativePath(projectDirectory),
"--output-path",
@ -26,7 +26,9 @@ extension StringsConfiguration: Runnable {
"--extension-output-path",
extensionOutputPath.prependIfRelativePath(projectDirectory),
"--static-members",
"\(staticMembersOptions)"
"\(staticMembersOptions)",
"--xc-strings",
"\(xcStringsOptions)"
]
if let extensionName = extensionName {

View File

@ -18,7 +18,7 @@ extension FileManager {
for case let fileURL as URL in enumerator {
do {
let fileAttributes = try fileURL.resourceValues(forKeys:[.isRegularFileKey])
let fileAttributes = try fileURL.resourceValues(forKeys: [.isRegularFileKey])
if fileAttributes.isRegularFile! {
files.append(fileURL.relativePath)
}
@ -41,7 +41,7 @@ extension FileManager {
for case let fileURL as URL in enumerator {
do {
let fileAttributes = try fileURL.resourceValues(forKeys:[.isDirectoryKey])
let fileAttributes = try fileURL.resourceValues(forKeys: [.isDirectoryKey])
if fileAttributes.isDirectory! && fileURL.lastPathComponent.hasSuffix(".imageset") {
files.append(fileURL.lastPathComponent)
}

View File

@ -29,7 +29,7 @@ class ImageExtensionGenerator {
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
do {
try extensionContent.write(to: extensionFilePathURL, atomically: false, encoding: .utf8)
} catch (let error) {
} catch let error {
let error = ImagesError.writeFile(extensionFilePath, error.localizedDescription)
print(error.description)
Images.exit(withError: error)

View File

@ -8,10 +8,13 @@
import Foundation
import ToolCore
enum OutputImageExtension: String {
case png
case svg
}
class XcassetsGenerator {
static let outputImageExtension = "png"
let forceGeneration: Bool
// MARK: - Init
@ -60,13 +63,20 @@ class XcassetsGenerator {
generatedAssetsPaths.append(imagesetName)
// Generate output images path
let output1x = "\(imagesetPath)/\(parsedImage.name).\(XcassetsGenerator.outputImageExtension)"
let output2x = "\(imagesetPath)/\(parsedImage.name)@2x.\(XcassetsGenerator.outputImageExtension)"
let output3x = "\(imagesetPath)/\(parsedImage.name)@3x.\(XcassetsGenerator.outputImageExtension)"
let output1x = "\(imagesetPath)/\(parsedImage.name).\(OutputImageExtension.png.rawValue)"
let output2x = "\(imagesetPath)/\(parsedImage.name)@2x.\(OutputImageExtension.png.rawValue)"
let output3x = "\(imagesetPath)/\(parsedImage.name)@3x.\(OutputImageExtension.png.rawValue)"
// Check if we need to convert image
guard self.shouldGenerate(inputImagePath: imageData.path, xcassetImagePath: output1x) else {
//print("\(parsedImage.name) -> Not regenerating")
var needToGenerateForSvg = false
if imageData.ext == "svg" && !parsedImage.imageExtensions.contains(.png) {
needToGenerateForSvg = true
}
guard self.shouldGenerate(inputImagePath: imageData.path, xcassetImagePath: output1x, needToGenerateForSvg: needToGenerateForSvg) else {
print("\(parsedImage.name) -> Not regenerating")
return
}
@ -80,29 +90,55 @@ class XcassetsGenerator {
print(error.description)
Images.exit(withError: error)
}
} else {
do {
let documentsDirectory = try fileManager.contentsOfDirectory(atPath: imagesetPath)
for filePath in documentsDirectory {
try fileManager.removeItem(atPath: "\(imagesetPath)/\(filePath)")
}
} catch {
print("Error deleting previous assets")
}
}
// Convert image
let convertArguments = parsedImage.convertArguments
if imageData.ext == "svg" {
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -h 300 -o path/to/output.png
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -o path/to/output.png
// /usr/local/bin/rsvg-convert path/to/image.png -h 300 -o path/to/output.png
var command1x = ["\(svgConverter)", "\(imageData.path)"]
var command2x = ["\(svgConverter)", "\(imageData.path)"]
var command3x = ["\(svgConverter)", "\(imageData.path)"]
self.addConvertArgument(command: &command1x, convertArgument: convertArguments.x1)
self.addConvertArgument(command: &command2x, convertArgument: convertArguments.x2)
self.addConvertArgument(command: &command3x, convertArgument: convertArguments.x3)
command1x.append(contentsOf: ["-o", output1x])
command2x.append(contentsOf: ["-o", output2x])
command3x.append(contentsOf: ["-o", output3x])
Shell.shell(command1x)
Shell.shell(command2x)
Shell.shell(command3x)
if parsedImage.imageExtensions.contains(.png) {
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -h 300 -o path/to/output.png
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -o path/to/output.png
// /usr/local/bin/rsvg-convert path/to/image.png -h 300 -o path/to/output.png
var command1x = ["\(svgConverter)", "\(imageData.path)"]
var command2x = ["\(svgConverter)", "\(imageData.path)"]
var command3x = ["\(svgConverter)", "\(imageData.path)"]
self.addConvertArgument(command: &command1x, convertArgument: convertArguments.x1)
self.addConvertArgument(command: &command2x, convertArgument: convertArguments.x2)
self.addConvertArgument(command: &command3x, convertArgument: convertArguments.x3)
command1x.append(contentsOf: ["-o", output1x])
command2x.append(contentsOf: ["-o", output2x])
command3x.append(contentsOf: ["-o", output3x])
Shell.shell(command1x)
Shell.shell(command2x)
Shell.shell(command3x)
} else {
let output = "\(imagesetPath)/\(parsedImage.name).\(OutputImageExtension.svg.rawValue)"
let tempURL = URL(fileURLWithPath: output)
do {
if FileManager.default.fileExists(atPath: tempURL.path) {
try FileManager.default.removeItem(atPath: tempURL.path)
}
try FileManager.default.copyItem(atPath: imageData.path, toPath: tempURL.path)
} catch {
print(error.localizedDescription)
}
}
} else {
// convert path/to/image.png -resize 200x300 path/to/output.png
// convert path/to/image.png -resize 200x path/to/output.png
@ -119,7 +155,7 @@ class XcassetsGenerator {
}
// Write Content.json
let imagesetContentJson = parsedImage.contentJson
guard let imagesetContentJson = parsedImage.generateContentJson(isVector: imageData.ext == "svg") else { return }
let contentJsonFilePath = "\(imagesetPath)/Contents.json"
let contentJsonFilePathURL = URL(fileURLWithPath: contentJsonFilePath)
@ -161,8 +197,8 @@ class XcassetsGenerator {
// MARK: - Helpers: bypass generation
private func shouldGenerate(inputImagePath: String, xcassetImagePath: String) -> Bool {
if forceGeneration {
private func shouldGenerate(inputImagePath: String, xcassetImagePath: String, needToGenerateForSvg: Bool) -> Bool {
if forceGeneration || needToGenerateForSvg {
return true
}

View File

@ -21,8 +21,8 @@ struct Images: ParsableCommand {
// MARK: - Static
static let toolName = "Images"
static let defaultExtensionName = "UIImage"
static let defaultExtensionNameSUI = "Image"
static let defaultExtensionName = "Image"
static let defaultExtensionNameUIKit = "UIImage"
// MARK: - Command Options
@ -58,14 +58,14 @@ struct Images: ParsableCommand {
inputFilename: options.inputFilenameWithoutExt,
extensionName: options.extensionName,
extensionFilePath: options.extensionFilePath,
isSwiftUI: false)
isSwiftUI: true)
ImageExtensionGenerator.generateExtensionFile(images: imagesToGenerate,
staticVar: options.staticMembers,
inputFilename: options.inputFilenameWithoutExt,
extensionName: options.extensionNameSwiftUI,
extensionFilePath: options.extensionFilePathSwiftUI,
isSwiftUI: true)
extensionName: options.extensionNameUIKit,
extensionFilePath: options.extensionFilePathUIKit,
isSwiftUI: false)
print("[\(Self.toolName)] Images generated")
}
@ -90,7 +90,7 @@ struct Images: ParsableCommand {
_ = Images.getSvgConverterPath()
// Extension for UIKit and SwiftUI should have different name
guard options.extensionName != options.extensionNameSwiftUI else {
guard options.extensionName != options.extensionNameUIKit else {
let error = ImagesError.extensionNamesCollision(options.extensionName)
print(error.description)
Images.exit(withError: error)

View File

@ -27,11 +27,11 @@ struct ImagesOptions: ParsableArguments {
@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.")
@Option(help: "Extension name. If not specified, it will generate an Image 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 name. If not specified, it will generate an UIImage extension.")
var extensionNameUIKit: String = Images.defaultExtensionNameUIKit
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+Image{extensionSuffix}.swift")
var extensionSuffix: String?
@ -41,7 +41,7 @@ struct ImagesOptions: ParsableArguments {
extension ImagesOptions {
// MARK: - UIKit
// MARK: - SwiftUI
var extensionFileName: String {
if let extensionSuffix = extensionSuffix {
@ -54,17 +54,17 @@ extension ImagesOptions {
"\(extensionOutputPath)/\(extensionFileName)"
}
// MARK: - SwiftUI
// MARK: - UIKit
var extensionFileNameSwiftUI: String {
var extensionFileNameUIKit: String {
if let extensionSuffix = extensionSuffix {
return "\(extensionNameSwiftUI)+\(extensionSuffix).swift"
return "\(extensionNameUIKit)+\(extensionSuffix).swift"
}
return "\(extensionNameSwiftUI).swift"
return "\(extensionNameUIKit).swift"
}
var extensionFilePathSwiftUI: String {
"\(extensionOutputPath)/\(extensionFileNameSwiftUI)"
var extensionFilePathUIKit: String {
"\(extensionOutputPath)/\(extensionFileNameUIKit)"
}
// MARK: -

View File

@ -0,0 +1,76 @@
//
// ImageContent.swift
//
//
// Created by Quentin Bandera on 19/04/2024.
//
import Foundation
enum TemplateRenderingIntent: String, Codable {
case template
case original
}
struct AssetContent: Codable, Equatable {
let images: [AssetImageDescription]
let info: AssetInfo
let properties: AssetProperties?
init(
images: [AssetImageDescription],
info: AssetInfo,
properties: AssetProperties? = nil
) {
self.images = images
self.info = info
self.properties = properties
}
static func == (lhs: AssetContent, rhs: AssetContent) -> Bool {
guard lhs.images.count == rhs.images.count else { return false }
let lhsImages = lhs.images.sorted(by: { $0.filename < $1.filename })
let rhsImages = rhs.images.sorted(by: { $0.filename < $1.filename })
return lhsImages == rhsImages
}
}
struct AssetImageDescription: Codable, Equatable {
let idiom: String
let scale: String?
let filename: String
init(
idiom: String,
scale: String? = nil,
filename: String
) {
self.idiom = idiom
self.scale = scale
self.filename = filename
}
}
struct AssetInfo: Codable, Equatable {
let version: Int
let author: String
}
struct AssetProperties: Codable, Equatable {
let preservesVectorRepresentation: Bool
let templateRenderingIntent: TemplateRenderingIntent?
init(
preservesVectorRepresentation: Bool,
templateRenderingIntent: TemplateRenderingIntent? = nil
) {
self.preservesVectorRepresentation = preservesVectorRepresentation
self.templateRenderingIntent = templateRenderingIntent
}
enum CodingKeys: String, CodingKey {
case preservesVectorRepresentation = "preserves-vector-representation"
case templateRenderingIntent = "template-rendering-intent"
}
}

View File

@ -7,12 +7,31 @@
import Foundation
enum ImageExtension: String {
case png
}
struct ParsedImage {
let name: String
let tags: String
let width: Int
let height: Int
let imageExtensions: [ImageExtension]
init(
name: String,
tags: String,
width: Int,
height: Int,
imageExtensions: [ImageExtension] = []
) {
self.name = name
self.tags = tags
self.width = width
self.height = height
self.imageExtensions = imageExtensions
}
// MARK: - Convert
var convertArguments: (x1: ConvertArgument, x2: ConvertArgument, x3: ConvertArgument) {
@ -42,34 +61,69 @@ struct ParsedImage {
// MARK: - Assets
var contentJson: String {
"""
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "\(name).\(XcassetsGenerator.outputImageExtension)"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "\(name)@2x.\(XcassetsGenerator.outputImageExtension)"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "\(name)@3x.\(XcassetsGenerator.outputImageExtension)"
}
],
"info" : {
"version" : 1,
"author" : "ResgenSwift-Imagium"
}
func generateContentJson(isVector: Bool) -> String? {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let imageContent = generateImageContent(isVector: isVector)
guard let data = try? encoder.encode(imageContent) else {
let error = ImagesError.writeFile("Contents.json", "Error encoding json file")
print(error.description)
Images.exit(withError: error)
}
"""
return String(data: data, encoding: .utf8)
}
func generateImageContent(isVector: Bool) -> AssetContent {
if !imageExtensions.contains(.png) && isVector {
//Generate svg
return AssetContent(
images: [
AssetImageDescription(
idiom: "universal",
filename: "\(name).\(OutputImageExtension.svg.rawValue)"
)
],
info: AssetInfo(
version: 1,
author: "ResgenSwift-Imagium"
),
properties: AssetProperties(
preservesVectorRepresentation: true,
templateRenderingIntent: .original
)
)
} else {
//Generate png
return AssetContent(
images: [
AssetImageDescription(
idiom: "universal",
scale: "1x",
filename: "\(name).\(OutputImageExtension.png.rawValue)"
),
AssetImageDescription(
idiom: "universal",
scale: "2x",
filename: "\(name)@2x.\(OutputImageExtension.png.rawValue)"
),
AssetImageDescription(
idiom: "universal",
scale: "3x",
filename: "\(name)@3x.\(OutputImageExtension.png.rawValue)"
)
],
info: AssetInfo(
version: 1,
author: "ResgenSwift-Imagium"
)
)
}
}
// MARK: - Extension property
func getImageProperty(isStatic: Bool, isSwiftUI: Bool) -> String {

View File

@ -38,11 +38,21 @@ class ImageFileParser {
}
return Int(splittedLine[3])!
}()
let image = ParsedImage(name: String(splittedLine[1]), tags: String(splittedLine[0]), width: width, height: height)
var imageExtensions: [ImageExtension] = []
splittedLine.forEach { stringExtension in
if let imageExtension = ImageExtension(rawValue: String(stringExtension)) {
imageExtensions.append(imageExtension)
}
}
let image = ParsedImage(name: String(splittedLine[1]), tags: String(splittedLine[0]), width: width, height: height, imageExtensions: imageExtensions)
imagesToGenerate.append(image)
}
print(imagesToGenerate)
return imagesToGenerate.filter {
$0.tags.contains(platform.rawValue)
}

View File

@ -1,6 +1,6 @@
//
// StringsFileGenerator.swift
//
//
//
// Created by Thibaut Schmitt on 04/01/2022.
//
@ -9,15 +9,16 @@ 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,
@ -25,23 +26,48 @@ class StringsFileGenerator {
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) {
} catch let error {
let error = StringiumError.writeFile(error.localizedDescription, stringsFilePath)
print(error.description)
Stringium.exit(withError: error)
}
}
}
static func writeXcStringsFiles(sections: [Section],
langs: [String],
defaultLang: String,
tags: [String],
outputPath: String,
inputFilenameWithoutExt: String) {
let fileContent: String = Self.generateXcStringsFileContent(
langs: langs,
defaultLang: defaultLang,
tags: tags,
sections: sections
)
let stringsFilePath = "\(outputPath)/\(inputFilenameWithoutExt).xcstrings"
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],
@ -53,13 +79,13 @@ class StringsFileGenerator {
* 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
@ -69,16 +95,16 @@ class StringsFileGenerator {
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 {
@ -88,12 +114,123 @@ class StringsFileGenerator {
}
}
}
return stringsFileContent
}
// MARK: - XcStrings Generation
static func generateXcStringsFileContent(langs: [String],
defaultLang: String,
tags inputTags: [String],
sections: [Section]) -> String {
let rootObject = generateRootObject(langs: langs, defaultLang: defaultLang, tags: inputTags, sections: sections)
let file = generateXcStringsFileContentFromRootObject(rootObject: rootObject)
return file
}
static func generateXcStringsFileContentFromRootObject(rootObject: Root) -> String {
do {
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted]
let json = try encoder.encode(rootObject)
if let jsonString = String(data: json, encoding: .utf8) {
return jsonString
}
} catch {
debugPrint("Failed to encode: \(error)")
}
return ""
}
static func generateRootObject(langs: [String],
defaultLang: String,
tags inputTags: [String],
sections: [Section]) -> Root {
var xcStringDefinitionTab: [XCStringDefinition] = []
sections.forEach { section in
// Check that at least one string will be generated
guard section.hasOneOrMoreMatchingTags(tags: inputTags) else {
return // Go to next section
}
section.definitions.forEach { definition in
var skipDefinition = false
var isNoTranslation = false
var localizationTab: [XCStringLocalization] = []
if definition.hasOneOrMoreMatchingTags(inputTags: inputTags) == false {
skipDefinition = true
}
if definition.tags.contains(Stringium.noTranslationTag) {
isNoTranslation = true
}
if !skipDefinition {
if isNoTranslation {
// Search for langs in yaml
for lang in langs {
if let value = definition.translations[defaultLang], !value.isEmpty {
let localization = XCStringLocalization(
lang: lang,
content: XCStringLocalizationLangContent(
stringUnit: DefaultStringUnit(state: "translated", value: value)
)
)
localizationTab.append(localization)
}
}
} else {
// Search for langs in twine
for (lang, value) in definition.translations where !value.isEmpty {
let localization = XCStringLocalization(
lang: lang,
content: XCStringLocalizationLangContent(
stringUnit: DefaultStringUnit(state: "translated", value: value)
)
)
localizationTab.append(localization)
}
}
let xcStringDefinition = XCStringDefinition(
title: definition.name,
content: XCStringDefinitionContent(
comment: definition.comment,
extractionState: "manual",
localizations: XCStringLocalizationContainer(
localizations: localizationTab
)
)
)
xcStringDefinitionTab.append(xcStringDefinition)
}
}
}
let xcStringContainer = XCStringDefinitionContainer(strings: xcStringDefinitionTab)
return Root(
sourceLanguage: defaultLang,
strings: xcStringContainer,
version: "1.0"
)
}
// MARK: - Extension file
static func writeExtensionFiles(sections: [Section],
defaultLang lang: String,
tags: [String],
@ -110,20 +247,20 @@ class StringsFileGenerator {
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) {
} 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],
@ -139,31 +276,31 @@ class StringsFileGenerator {
]
.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], extensionClassname: String, extensionSuffix: String) -> String {
var enumDefinition = "\n enum Key\(extensionSuffix.uppercasedFirst()): String {\n"
// Enum
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
@ -172,7 +309,7 @@ class StringsFileGenerator {
enumDefinition += " case \(definition.name) = \"\(definition.name)\"\n"
}
}
// KeyPath accessors
enumDefinition += "\n"
enumDefinition += " var keyPath: KeyPath<\(extensionClassname), String> {\n"
@ -182,7 +319,7 @@ class StringsFileGenerator {
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
@ -194,23 +331,23 @@ class StringsFileGenerator {
enumDefinition += " }\n" // Switch
enumDefinition += " }\n" // var keyPath
enumDefinition += " }" // Enum
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))"
}
@ -221,11 +358,11 @@ class StringsFileGenerator {
}
.joined(separator: "\n")
}
private static func getFooter() -> String {
"""
}
"""
}
}

View File

@ -22,7 +22,7 @@ class TagsGenerator {
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
do {
try extensionFileContent.write(to: extensionFilePathURL, atomically: false, encoding: .utf8)
} catch (let error) {
} catch let error {
let error = StringiumError.writeFile(extensionFilePath, error.localizedDescription)
print(error.description)
Stringium.exit(withError: error)

View File

@ -37,7 +37,7 @@ class Definition {
}
func hasOneOrMoreMatchingTags(inputTags: [String]) -> Bool {
if Set(inputTags).intersection(Set(self.tags)).isEmpty {
if Set(inputTags).isDisjoint(with: tags) {
return false
}
return true
@ -84,22 +84,29 @@ class Definition {
return (inputParameters: inputParameters, translationArguments: translationArguments)
}
private func getBaseProperty(lang: String, translation: String, isStatic: Bool) -> String {
private func getBaseProperty(lang: String, translation: String, isStatic: Bool, comment: String?) -> String {
"""
/// Translation in \(lang) :
/// \(translation)
///
/// Comment :
/// \(comment?.isEmpty == false ? comment! : "No comment")
\(isStatic ? "static ": "")var \(name): String {
NSLocalizedString("\(name)", tableName: kStringsFileName, bundle: Bundle.main, value: "\(translation)", comment: "")
NSLocalizedString("\(name)", tableName: kStringsFileName, bundle: Bundle.main, value: "\(translation)", comment: "\(comment ?? "")")
}
"""
}
private func getBaseMethod(lang: String, translation: String, isStatic: Bool, inputParameters: [String], translationArguments: [String]) -> String {
private func getBaseMethod(lang: String, translation: String, isStatic: Bool, inputParameters: [String], translationArguments: [String], comment: String?) -> String {
"""
/// Translation in \(lang) :
/// \(translation)
///
/// Comment :
/// \(comment?.isEmpty == false ? comment! : "No comment")
\(isStatic ? "static ": "")func \(name)(\(inputParameters.joined(separator: ", "))) -> String {
String(format: \(isStatic ? "Self" : "self").\(name), \(translationArguments.joined(separator: ", ")))
}
@ -114,8 +121,13 @@ class Definition {
}
// Generate property
let property = getBaseProperty(lang: lang, translation: translation, isStatic: false)
let property = getBaseProperty(
lang: lang,
translation: translation,
isStatic: false,
comment: self.comment
)
// Generate method
var method = ""
if let parameters = self.getStringParameters(input: translation) {
@ -123,7 +135,8 @@ class Definition {
translation: translation,
isStatic: false,
inputParameters: parameters.inputParameters,
translationArguments: parameters.translationArguments)
translationArguments: parameters.translationArguments,
comment: self.comment)
}
return property + method
@ -137,7 +150,12 @@ class Definition {
}
// Generate property
let property = getBaseProperty(lang: lang, translation: translation, isStatic: true)
let property = getBaseProperty(
lang: lang,
translation: translation,
isStatic: true,
comment: self.comment
)
// Generate method
var method = ""
@ -146,7 +164,8 @@ class Definition {
translation: translation,
isStatic: true,
inputParameters: parameters.inputParameters,
translationArguments: parameters.translationArguments)
translationArguments: parameters.translationArguments,
comment: self.comment)
}
return property + method
@ -160,10 +179,14 @@ class Definition {
print(error.description)
Stringium.exit(withError: error)
}
return """
/// Translation in \(lang) :
/// \(translation)
///
/// Comment :
/// \(comment?.isEmpty == false ? comment! : "No comment")
var \(name): String {
"\(translation)"
}
@ -180,6 +203,9 @@ class Definition {
return """
/// Translation in \(lang) :
/// \(translation)
///
/// Comment :
/// \(comment?.isEmpty == false ? comment! : "No comment")
static var \(name): String {
"\(translation)"
}

View File

@ -0,0 +1,109 @@
//
// XcString.swift
//
//
// Created by Quentin Bandera on 12/04/2024.
//
import SwiftUI
struct DynamicKey: CodingKey {
var intValue: Int?
init?(intValue: Int) {
self.intValue = intValue
self.stringValue = "\(intValue)"
}
var stringValue: String
init?(stringValue: String) {
self.stringValue = stringValue
}
}
struct Root: Codable, Equatable {
let sourceLanguage: String
let strings: XCStringDefinitionContainer
let version: String
}
struct XCStringDefinitionContainer: Codable, Equatable {
let strings: [XCStringDefinition]
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: DynamicKey.self)
for str in strings {
if let codingKey = DynamicKey(stringValue: str.title) {
try container.encode(str.content, forKey: codingKey)
}
}
}
static func == (lhs: XCStringDefinitionContainer, rhs: XCStringDefinitionContainer) -> Bool {
return lhs.strings.sorted(by: {
$0.title < $1.title
}) == rhs.strings.sorted(by: { $0.title < $1.title })
}
}
struct XCStringDefinition: Codable, Equatable {
let title: String // json key -> custom encoding methods
let content: XCStringDefinitionContent
}
struct XCStringDefinitionContent: Codable, Equatable {
let comment: String?
let extractionState: String
var localizations: XCStringLocalizationContainer
init(comment: String? = nil, extractionState: String, localizations: XCStringLocalizationContainer) {
self.comment = comment
self.extractionState = extractionState
self.localizations = localizations
}
}
struct XCStringLocalizationContainer: Codable, Equatable {
let localizations: [XCStringLocalization]
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: DynamicKey.self)
for loca in localizations {
if let codingKey = DynamicKey(stringValue: loca.lang) {
try container.encode(loca.content, forKey: codingKey)
}
}
}
static func == (lhs: XCStringLocalizationContainer, rhs: XCStringLocalizationContainer) -> Bool {
return lhs.localizations.count == rhs.localizations.count && lhs.localizations.sorted(by: { $0.lang < $1.lang }) == rhs.localizations.sorted(by: { $0.lang < $1.lang })
}
}
struct XCStringLocalization: Codable, Equatable {
let lang: String // json key -> custom encoding method
let content: XCStringLocalizationLangContent
}
struct XCStringLocalizationLangContent: Codable, Equatable {
let stringUnit: DefaultStringUnit
}
//enum VarationOrStringUnit: Encodable {
// case variations([Varation])
// case stringUnit: (DefaultStringUnit)
//
// func encode(to encoder: any Encoder) throws {
// if let varations {
//
// } else if let {
//
// }
// }
//}
struct DefaultStringUnit: Codable, Equatable {
let state: String
let value: String
}

View File

@ -43,13 +43,26 @@ struct Stringium: ParsableCommand {
let sections = TwineFileParser.parse(options.inputFile)
// Generate strings files
StringsFileGenerator.writeStringsFiles(sections: sections,
langs: options.langs,
defaultLang: options.defaultLang,
tags: options.tags,
outputPath: options.stringsFileOutputPath,
inputFilenameWithoutExt: options.inputFilenameWithoutExt)
print(options.xcStrings)
if !options.xcStrings {
print("[\(Self.toolName)] Will generate strings")
StringsFileGenerator.writeStringsFiles(sections: sections,
langs: options.langs,
defaultLang: options.defaultLang,
tags: options.tags,
outputPath: options.stringsFileOutputPath,
inputFilenameWithoutExt: options.inputFilenameWithoutExt)
} else {
print("[\(Self.toolName)] Will generate xcStrings")
StringsFileGenerator.writeXcStringsFiles(sections: sections,
langs: options.langs,
defaultLang: options.defaultLang,
tags: options.tags,
outputPath: options.stringsFileOutputPath,
inputFilenameWithoutExt: options.inputFilenameWithoutExt)
}
// Generate extension
StringsFileGenerator.writeExtensionFiles(sections: sections,
defaultLang: options.defaultLang,
@ -59,7 +72,7 @@ struct Stringium: ParsableCommand {
extensionName: options.extensionName,
extensionFilePath: options.extensionFilePath,
extensionSuffix: options.extensionSuffix)
print("[\(Self.toolName)] Strings generated")
}

View File

@ -11,8 +11,8 @@ import ArgumentParser
struct StringiumOptions: ParsableArguments {
@Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation")
var forceGeneration = false
@Argument(help: "Input files where strings ared defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
@Argument(help: "Input files where strings are defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
var inputFile: String
@Option(name: .customLong("output-path"), help: "Path where to strings file.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
@ -32,7 +32,10 @@ struct StringiumOptions: ParsableArguments {
@Option(help: "Tell if it will generate static properties or not")
var staticMembers: Bool = false
@Option(help: "Tell if it will generate xcStrings file or not")
var xcStrings: Bool = false
@Option(help: "Extension name. If not specified, it will generate an String extension.")
var extensionName: String = Stringium.defaultExtensionName

View File

@ -27,4 +27,3 @@ struct Strings: ParsableCommand {
}
//Strings.main()

View File

@ -18,7 +18,6 @@ struct Tags: ParsableCommand {
version: ResgenSwiftVersion
)
// MARK: - Static
static let toolName = "Tags"

View File

@ -91,7 +91,7 @@ final class ParsedColorTests: XCTestCase {
// When
let contentJson = color.contentsJSON()
guard let data = contentJson.data(using: .utf8),
let parsedJson = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
let parsedJson = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
XCTFail("Cannot convert `contentJSON` string to Data")
return
}

View File

@ -21,7 +21,7 @@ final class ColorsConfigurationTests: XCTestCase {
xcassetsPath: "path/to/assets.xcassets",
extensionOutputPath: "Colors/Generated",
extensionName: nil,
extensionNameSwiftUI: nil,
extensionNameUIKit: nil,
extensionSuffix: nil,
staticMembers: false)
// When
@ -50,7 +50,7 @@ final class ColorsConfigurationTests: XCTestCase {
xcassetsPath: "path/to/assets.xcassets",
extensionOutputPath: "Colors/Generated",
extensionName: "AppUIColor",
extensionNameSwiftUI: "AppColor",
extensionNameUIKit: "AppColor",
extensionSuffix: "Testing",
staticMembers: false)
// When
@ -70,7 +70,7 @@ final class ColorsConfigurationTests: XCTestCase {
"false",
"--extension-name",
"AppUIColor",
"--extension-name-swift-ui",
"--extension-name-ui-kit",
"AppColor",
"--extension-suffix",
"Testing",

View File

@ -19,7 +19,7 @@ final class FontsConfigurationTests: XCTestCase {
let testingConfiguration = FontsConfiguration(inputFile: "path/to/fonts.txt",
extensionOutputPath: "Fonts/Generated",
extensionName: nil,
extensionNameSwiftUI: nil,
extensionNameUIKit: nil,
extensionSuffix: nil,
infoPlistPaths: nil,
staticMembers: nil)
@ -43,7 +43,7 @@ final class FontsConfigurationTests: XCTestCase {
let testingConfiguration = FontsConfiguration(inputFile: "path/to/fonts.txt",
extensionOutputPath: "Fonts/Generated",
extensionName: "AppUIFont",
extensionNameSwiftUI: "AppFont",
extensionNameUIKit: "AppFont",
extensionSuffix: "Testing",
infoPlistPaths: "path/to/plist1.plist path/to/plist2.plist",
staticMembers: true)
@ -60,7 +60,7 @@ final class FontsConfigurationTests: XCTestCase {
"true",
"--extension-name",
"AppUIFont",
"--extension-name-swift-ui",
"--extension-name-ui-kit",
"AppFont",
"--extension-suffix",
"Testing",

View File

@ -20,7 +20,7 @@ final class ImagesConfigurationTests: XCTestCase {
xcassetsPath: "path/to/assets.xcassets",
extensionOutputPath: "Images/Generated",
extensionName: nil,
extensionNameSwiftUI: nil,
extensionNameUIKit: nil,
extensionSuffix: nil,
staticMembers: nil)
@ -47,7 +47,7 @@ final class ImagesConfigurationTests: XCTestCase {
xcassetsPath: "path/to/assets.xcassets",
extensionOutputPath: "Images/Generated",
extensionName: "AppUIImage",
extensionNameSwiftUI: "AppImage",
extensionNameUIKit: "AppImage",
extensionSuffix: "Testing",
staticMembers: true)
@ -66,7 +66,7 @@ final class ImagesConfigurationTests: XCTestCase {
"true",
"--extension-name",
"AppUIImage",
"--extension-name-swift-ui",
"--extension-name-ui-kit",
"AppImage",
"--extension-suffix",
"Testing",

View File

@ -17,8 +17,8 @@ class ImageFileParserTests: XCTestCase {
#
# SMAAS Support
#
id image_one 25 ?
di image_two ? 50
id image_one 25 ? png
di image_two ? 50 webp png
d image_three 25 ?
d image_four 75 ?
"""
@ -38,13 +38,15 @@ class ImageFileParserTests: XCTestCase {
XCTAssertEqual(firstImage!.tags, "id")
XCTAssertEqual(firstImage!.width, 25)
XCTAssertEqual(firstImage!.height, -1)
XCTAssertEqual(firstImage!.imageExtensions, [.png])
let secondImage = parsedImages.first {
$0.name == "image_two"
}
XCTAssertEqual(secondImage!.name, "image_two")
XCTAssertEqual(secondImage!.tags, "di")
XCTAssertEqual(secondImage!.width, -1)
XCTAssertEqual(secondImage!.height, 50)
XCTAssertEqual(secondImage!.height, 50)
XCTAssertEqual(firstImage!.imageExtensions, [.png])
}
}

View File

@ -127,35 +127,77 @@ final class ParsedImageTests: XCTestCase {
height: 10)
// When
let property = parsedImage.contentJson
let property = parsedImage.generateImageContent(isVector: false)
// Expect
let expect = """
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "\(imageName).\(XcassetsGenerator.outputImageExtension)"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "\(imageName)@2x.\(XcassetsGenerator.outputImageExtension)"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "\(imageName)@3x.\(XcassetsGenerator.outputImageExtension)"
}
],
"info" : {
"version" : 1,
"author" : "ResgenSwift-Imagium"
}
}
"""
XCTAssertEqual(property.adaptForXCTest(), expect.adaptForXCTest())
let expect = AssetContent(
images: [
AssetImageDescription(
idiom: "universal",
scale: "1x",
filename: "\(parsedImage.name).\(OutputImageExtension.png.rawValue)"
),
AssetImageDescription(
idiom: "universal",
scale: "2x",
filename: "\(parsedImage.name)@2x.\(OutputImageExtension.png.rawValue)"
),
AssetImageDescription(
idiom: "universal",
scale: "3x",
filename: "\(parsedImage.name)@3x.\(OutputImageExtension.png.rawValue)"
)
],
info: AssetInfo(
version: 1,
author: "ResgenSwift-Imagium"
)
)
XCTAssertEqual(property, expect)
}
func testAssetPng() {
// Given
let imageName = "the_name"
let parsedImage = ParsedImage(name: imageName,
tags: "id",
width: 10,
height: 10,
imageExtensions: [.png])
// When
let property = parsedImage.generateImageContent(isVector: false)
// Expect
let expect = AssetContent(
images: [
AssetImageDescription(
idiom: "universal",
scale: "1x",
filename: "\(parsedImage.name).\(OutputImageExtension.png.rawValue)"
),
AssetImageDescription(
idiom: "universal",
scale: "2x",
filename: "\(parsedImage.name)@2x.\(OutputImageExtension.png.rawValue)"
),
AssetImageDescription(
idiom: "universal",
scale: "3x",
filename: "\(parsedImage.name)@3x.\(OutputImageExtension.png.rawValue)"
)
],
info: AssetInfo(
version: 1,
author: "ResgenSwift-Imagium"
)
)
debugPrint(property)
debugPrint(expect)
XCTAssertEqual(property, expect)
}
}

View File

@ -100,24 +100,33 @@ final class DefinitionTests: XCTestCase {
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// This is a comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "")
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "This is a comment")
}
"""
let expectEn = """
/// Translation in en :
/// This is the english translation
///
/// Comment :
/// This is a comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "")
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "This is a comment")
}
"""
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// This is a comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "")
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "This is a comment")
}
"""
@ -125,7 +134,118 @@ final class DefinitionTests: XCTestCase {
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
func testGeneratedNSLocalizedStringPropertyWithEmptyComment() {
// Given
let definition = Definition(name: "definition_name")
definition.tags = ["ios","iosonly","notranslation"]
definition.comment = ""
definition.translations = [
"fr": "C'est la traduction francaise",
"en": "This is the english translation",
"en-us": "This is the english us translation"
]
// When
let propertyFr = definition.getNSLocalizedStringProperty(forLang: "fr")
let propertyEn = definition.getNSLocalizedStringProperty(forLang: "en")
let propertyEnUs = definition.getNSLocalizedStringProperty(forLang: "en-us")
// Expect
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// No comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "")
}
"""
let expectEn = """
/// Translation in en :
/// This is the english translation
///
/// Comment :
/// No comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "")
}
"""
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// No comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "")
}
"""
XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest())
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
func testGeneratedNSLocalizedStringPropertyWithNoComment() {
// Given
let definition = Definition(name: "definition_name")
definition.tags = ["ios","iosonly","notranslation"]
definition.translations = [
"fr": "C'est la traduction francaise",
"en": "This is the english translation",
"en-us": "This is the english us translation"
]
// When
let propertyFr = definition.getNSLocalizedStringProperty(forLang: "fr")
let propertyEn = definition.getNSLocalizedStringProperty(forLang: "en")
let propertyEnUs = definition.getNSLocalizedStringProperty(forLang: "en-us")
// Expect
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// No comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "")
}
"""
let expectEn = """
/// Translation in en :
/// This is the english translation
///
/// Comment :
/// No comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "")
}
"""
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// No comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "")
}
"""
XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest())
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
// MARK: - getNSLocalizedStringStaticProperty
func testGeneratedNSLocalizedStringStaticProperty() {
// Given
let definition = Definition(name: "definition_name")
@ -146,24 +266,33 @@ final class DefinitionTests: XCTestCase {
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// This is a comment
static var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "")
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "This is a comment")
}
"""
let expectEn = """
/// Translation in en :
/// This is the english translation
///
/// Comment :
/// This is a comment
static var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "")
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "This is a comment")
}
"""
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// This is a comment
static var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "")
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "This is a comment")
}
"""
@ -171,7 +300,116 @@ final class DefinitionTests: XCTestCase {
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
func testGeneratedNSLocalizedStringStaticPropertyWithEmptyComment() {
// Given
let definition = Definition(name: "definition_name")
definition.tags = ["ios","iosonly","notranslation"]
definition.comment = ""
definition.translations = [
"fr": "C'est la traduction francaise",
"en": "This is the english translation",
"en-us": "This is the english us translation"
]
// When
let propertyFr = definition.getNSLocalizedStringStaticProperty(forLang: "fr")
let propertyEn = definition.getNSLocalizedStringStaticProperty(forLang: "en")
let propertyEnUs = definition.getNSLocalizedStringStaticProperty(forLang: "en-us")
// Expect
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// No comment
static var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "")
}
"""
let expectEn = """
/// Translation in en :
/// This is the english translation
///
/// Comment :
/// No comment
static var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "")
}
"""
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// No comment
static var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "")
}
"""
XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest())
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
func testGeneratedNSLocalizedStringStaticPropertyWithNoComment() {
// Given
let definition = Definition(name: "definition_name")
definition.tags = ["ios","iosonly","notranslation"]
definition.translations = [
"fr": "C'est la traduction francaise",
"en": "This is the english translation",
"en-us": "This is the english us translation"
]
// When
let propertyFr = definition.getNSLocalizedStringStaticProperty(forLang: "fr")
let propertyEn = definition.getNSLocalizedStringStaticProperty(forLang: "en")
let propertyEnUs = definition.getNSLocalizedStringStaticProperty(forLang: "en-us")
// Expect
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// No comment
static var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "")
}
"""
let expectEn = """
/// Translation in en :
/// This is the english translation
///
/// Comment :
/// No comment
static var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "")
}
"""
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// No comment
static var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "")
}
"""
XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest())
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
func testGeneratedNSLocalizedStringPropertyWithOneArgument() {
// Given
let definition = Definition(name: "definition_name")
@ -188,17 +426,23 @@ final class DefinitionTests: XCTestCase {
let expectFr = """
/// Translation in fr :
/// Welcome "%@" !
///
/// Comment :
/// This is a comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" !", comment: "")
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" !", comment: "This is a comment")
}
/// Translation in fr :
/// Welcome "%@" !
///
/// Comment :
/// This is a comment
func definition_name(arg0: String) -> String {
String(format: self.definition_name, arg0)
}
"""
XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest())
}
@ -218,12 +462,18 @@ final class DefinitionTests: XCTestCase {
let expectFr = """
/// Translation in fr :
/// Welcome "%@" ! Your age is %d :) Your weight is %f ;-)
///
/// Comment :
/// This is a comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" ! Your age is %d :) Your weight is %f ;-)", comment: "")
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" ! Your age is %d :) Your weight is %f ;-)", comment: "This is a comment")
}
/// Translation in fr :
/// Welcome "%@" ! Your age is %d :) Your weight is %f ;-)
///
/// Comment :
/// This is a comment
func definition_name(arg0: String, arg1: Int, arg2: Double) -> String {
String(format: self.definition_name, arg0, arg1, arg2)
}
@ -249,12 +499,18 @@ final class DefinitionTests: XCTestCase {
let expectFr = """
/// Translation in fr :
/// Vous %%: %1$@ %2$@ Age: %3$d
///
/// Comment :
/// This is a comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Vous %%: %1$@ %2$@ Age: %3$d", comment: "")
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Vous %%: %1$@ %2$@ Age: %3$d", comment: "This is a comment")
}
/// Translation in fr :
/// Vous %%: %1$@ %2$@ Age: %3$d
///
/// Comment :
/// This is a comment
func definition_name(arg0: String, arg1: String, arg2: Int) -> String {
String(format: self.definition_name, arg0, arg1, arg2)
}
@ -263,12 +519,18 @@ final class DefinitionTests: XCTestCase {
let expectEn = """
/// Translation in en :
/// You %%: %2$@ %1$@ Age: %3$d
///
/// Comment :
/// This is a comment
var definition_name: String {
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "You %%: %2$@ %1$@ Age: %3$d", comment: "")
NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "You %%: %2$@ %1$@ Age: %3$d", comment: "This is a comment")
}
/// Translation in en :
/// You %%: %2$@ %1$@ Age: %3$d
///
/// Comment :
/// This is a comment
func definition_name(arg0: String, arg1: String, arg2: Int) -> String {
String(format: self.definition_name, arg0, arg1, arg2)
}
@ -300,6 +562,9 @@ final class DefinitionTests: XCTestCase {
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// This is a comment
var definition_name: String {
"C'est la traduction francaise"
}
@ -308,6 +573,9 @@ final class DefinitionTests: XCTestCase {
let expectEn = """
/// Translation in en :
/// This is the english translation
///
/// Comment :
/// This is a comment
var definition_name: String {
"This is the english translation"
}
@ -316,6 +584,9 @@ final class DefinitionTests: XCTestCase {
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// This is a comment
var definition_name: String {
"This is the english us translation"
}
@ -325,7 +596,118 @@ final class DefinitionTests: XCTestCase {
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
func testGeneratedRawPropertyWithEmptyComment() {
// Given
let definition = Definition(name: "definition_name")
definition.tags = ["ios","iosonly","notranslation"]
definition.comment = ""
definition.translations = [
"fr": "C'est la traduction francaise",
"en": "This is the english translation",
"en-us": "This is the english us translation"
]
// When
let propertyFr = definition.getProperty(forLang: "fr")
let propertyEn = definition.getProperty(forLang: "en")
let propertyEnUs = definition.getProperty(forLang: "en-us")
// Expect
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// No comment
var definition_name: String {
"C'est la traduction francaise"
}
"""
let expectEn = """
/// Translation in en :
/// This is the english translation
///
/// Comment :
/// No comment
var definition_name: String {
"This is the english translation"
}
"""
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// No comment
var definition_name: String {
"This is the english us translation"
}
"""
XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest())
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
func testGeneratedRawPropertyWithNoComment() {
// Given
let definition = Definition(name: "definition_name")
definition.tags = ["ios","iosonly","notranslation"]
definition.translations = [
"fr": "C'est la traduction francaise",
"en": "This is the english translation",
"en-us": "This is the english us translation"
]
// When
let propertyFr = definition.getProperty(forLang: "fr")
let propertyEn = definition.getProperty(forLang: "en")
let propertyEnUs = definition.getProperty(forLang: "en-us")
// Expect
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// No comment
var definition_name: String {
"C'est la traduction francaise"
}
"""
let expectEn = """
/// Translation in en :
/// This is the english translation
///
/// Comment :
/// No comment
var definition_name: String {
"This is the english translation"
}
"""
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// No comment
var definition_name: String {
"This is the english us translation"
}
"""
XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest())
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
// MARK: - Raw static properties
func testGeneratedRawStaticProperty() {
// Given
let definition = Definition(name: "definition_name")
@ -346,6 +728,9 @@ final class DefinitionTests: XCTestCase {
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// This is a comment
static var definition_name: String {
"C'est la traduction francaise"
}
@ -354,7 +739,10 @@ final class DefinitionTests: XCTestCase {
let expectEn = """
/// Translation in en :
/// This is the english translation
static var definition_name: String {
///
/// Comment :
/// This is a comment
static var definition_name: String {
"This is the english translation"
}
"""
@ -362,6 +750,9 @@ final class DefinitionTests: XCTestCase {
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// This is a comment
static var definition_name: String {
"This is the english us translation"
}
@ -371,4 +762,113 @@ final class DefinitionTests: XCTestCase {
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
func testGeneratedRawStaticPropertyWithEmptyComment() {
// Given
let definition = Definition(name: "definition_name")
definition.tags = ["ios","iosonly","notranslation"]
definition.comment = ""
definition.translations = [
"fr": "C'est la traduction francaise",
"en": "This is the english translation",
"en-us": "This is the english us translation"
]
// When
let propertyFr = definition.getStaticProperty(forLang: "fr")
let propertyEn = definition.getStaticProperty(forLang: "en")
let propertyEnUs = definition.getStaticProperty(forLang: "en-us")
// Expect
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// No comment
static var definition_name: String {
"C'est la traduction francaise"
}
"""
let expectEn = """
/// Translation in en :
/// This is the english translation
///
/// Comment :
/// No comment
static var definition_name: String {
"This is the english translation"
}
"""
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// No comment
static var definition_name: String {
"This is the english us translation"
}
"""
XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest())
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
func testGeneratedRawStaticPropertyWithNoComment() {
// Given
let definition = Definition(name: "definition_name")
definition.tags = ["ios","iosonly","notranslation"]
definition.translations = [
"fr": "C'est la traduction francaise",
"en": "This is the english translation",
"en-us": "This is the english us translation"
]
// When
let propertyFr = definition.getStaticProperty(forLang: "fr")
let propertyEn = definition.getStaticProperty(forLang: "en")
let propertyEnUs = definition.getStaticProperty(forLang: "en-us")
// Expect
let expectFr = """
/// Translation in fr :
/// C'est la traduction francaise
///
/// Comment :
/// No comment
static var definition_name: String {
"C'est la traduction francaise"
}
"""
let expectEn = """
/// Translation in en :
/// This is the english translation
///
/// Comment :
/// No comment
static var definition_name: String {
"This is the english translation"
}
"""
let expectEnUs = """
/// Translation in en-us :
/// This is the english us translation
///
/// Comment :
/// No comment
static var definition_name: String {
"This is the english us translation"
}
"""
XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest())
XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest())
XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest())
}
}

File diff suppressed because it is too large Load Diff

48
script/swiftlint.sh Executable file
View File

@ -0,0 +1,48 @@
#!/bin/sh
# Go to git repo root level
cd $(git rev-parse --show-toplevel)
if [[ "$BUILD_DIR" == *"IBDesignables"* ]] || [[ "$BUILD_DIR" == *"Previews"* ]] ; then
echo "not linting for IBDesignables/SwiftUI Previews builds";
exit 0
fi
SWIFT_LINT=$(which swiftlint)
if [[ -z $SWIFT_LINT ]] ; then
echo "warning: SwiftLint not installed, please download it from https://github.com/realm/SwiftLint"
exit 0
fi
if [[ $RUN_CLANG_STATIC_ANALYZER == "YES" ]] ; then
time $SWIFT_LINT
else
COUNT=0
##### Check for modified git files #####
FILES=$(git diff --name-only | grep -iv "^carthage" | grep -iv "^pods" | grep -iv "^vendor" | grep -v "R2" | grep ".swift$")
if [ ! -z "$FILES" ]; then
while read FILE_PATH; do
export SCRIPT_INPUT_FILE_$COUNT=$FILE_PATH
COUNT=$((COUNT + 1))
done <<< "$FILES"
fi
##### Check for modified files in unstaged/Staged area #####
FILES=$(git diff --name-only --cached --diff-filter=d | grep -iv "^carthage" | grep -iv "^pods" | grep -iv "^vendor" | grep -v "R2" | grep ".swift$")
if [ ! -z "$FILES" ]; then
while read FILE_PATH; do
export SCRIPT_INPUT_FILE_$COUNT=$FILE_PATH
COUNT=$((COUNT + 1))
done <<< "$FILES"
fi
##### Make the count avilable as global variable #####
export SCRIPT_INPUT_FILE_COUNT=$COUNT
env | grep SCRIPT_INPUT_FILE_
if [[ COUNT -ne 0 ]] ; then
time $SWIFT_LINT --use-script-input-files
fi
fi