4 Commits

Author SHA1 Message Date
f0131e0828 Add Swiftlint
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
2023-12-08 17:10:21 +01:00
3d675a5663 Fix Image
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
2023-12-08 16:28:58 +01:00
92d0a51116 Fix Font 2023-12-08 16:21:14 +01:00
3bcae91725 Fix Color 2023-12-08 16:15:28 +01:00
31 changed files with 228 additions and 552 deletions

View File

@ -18,15 +18,6 @@
"version" : "1.8.0"
}
},
{
"identity" : "pathkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/kylef/PathKit.git",
"state" : {
"revision" : "3bfd2737b700b9a36565a8c94f4ad2b050a5e574",
"version" : "1.0.1"
}
},
{
"identity" : "sourcekitten",
"kind" : "remoteSourceControl",
@ -36,24 +27,6 @@
"version" : "0.34.1"
}
},
{
"identity" : "spectre",
"kind" : "remoteSourceControl",
"location" : "https://github.com/kylef/Spectre.git",
"state" : {
"revision" : "26cc5e9ae0947092c7139ef7ba612e34646086c7",
"version" : "0.10.1"
}
},
{
"identity" : "stencil",
"kind" : "remoteSourceControl",
"location" : "https://github.com/stencilproject/Stencil.git",
"state" : {
"revision" : "4f222ac85d673f35df29962fc4c36ccfdaf9da5b",
"version" : "0.15.1"
}
},
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",

View File

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

View File

@ -133,71 +133,6 @@ swift run -c release ResgenSwift strings tags $FORCE_FLAG "./Tags/tags.txt" \
> ⚠️ If extension name is not set or is `Tags`, it will generate the following typaloas `typealias Tags = String`.
## Analytics
Analytics will generate all you need to analyze UX with Matomo or Firebase Analytics. Input files are formatted in YAML. This command will generate a manager for each target and an AnalyticsManager. This is this one you will need to use. And it will generate a method for all tags you have declared in the YAML file. Next, you will need to use the `configure()` method of AnalyticsManager and if you want to use matomo to set up the `siteId` and the `url` of the site.
```sh
swift run -c release ResgenSwift strings tags $FORCE_FLAG "./Tags/tags.txt" \
--target "matomo firebase" \
--extension-output-path "./Analytics/Generated" \
--extension-name "AppAnalytics" \
--extension-suffix "GreatApp" \
--static-members true
```
**Parameters**
1. `-f`: force generation
2. Input tags file (must be YAML formatted)
3. `--target`: target with you will log UX
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: `AppAnalytics+GreatApp.swift`)
7. `--static-members` *(optional)*: generate static properties or not
> ⚠️ If extension name is not set or is `Analytics`, it will generate the following typaloas `typealias Analytics = String`.
### YAML
```
- id: s1_def_one
name: s1 def one _TITLE_
path: s1_def_one/_TITLE_
action: Tap
category: User
tags: ios,droid
comments:
parameters:
- name: title
type: String
replaceIn: name,path
```
1. `id`: name of the method (method name will be composed of `log` + `Event|Screen` + `id`)
2. `name`: name of the tag
3. `path` *(optional with firebase)* : needed for matomo but not with firebase (log screen)
4. `action` *(optional with firebase)* : needed for matomo but not with firebase (log event)
5. `category` *(optional with firebase)* : needed for matomo but not with firebase (log event)
6. `tags`: which platform target
7. `comments` *(optional)*
8. `parameters` *(optional)*
**Parameters**
You can use parameters in generate methods.
1. `name`: name of the parameter
2. `type`: type of the parameter (Int, String, Bool, Double)
3. `replaceIn` *(optional)*
**Replace in**
This is section is equivalent of `%s | %d | %f | %@`. You can put the content of the parameter in *name*, *path*, *action*, *category*.
You need to put `_` + `NAME OF THE PARAMETER` + `_` in the target and which target you want in the value of `replaceIn`. (name need to be in uppercase)
## Images
Images generator will generate images assets along with extensions to access those images easily.

View File

@ -4,25 +4,18 @@ import SwiftUI
extension ColorYolo {
/// Color red is #FF0000 #FF0000 or #FF0000 #FF0000"
/// Color red is #FF0000 (light) or #FF0000 (dark)"
var red: Color {
Color("red")
}
/// Color green_alpha_50 is #A000FF00 #A000FF00 or #A000FF00 #A000FF00"
/// Color green_alpha_50 is #A000FF00 (light) or #A000FF00 (dark)"
var green_alpha_50: Color {
Color("green_alpha_50")
}
/// Color blue_light_dark is #0000FF #0000FF or #0000AA #0000AA"
/// Color blue_light_dark is #0000FF (light) or #0000AA (dark)"
var blue_light_dark: Color {
Color("blue_light_dark")
}
}

View File

@ -4,25 +4,18 @@ import UIKit
extension UIColorYolo {
/// Color red is #FF0000 #FF0000 or #FF0000 #FF0000"
/// Color red is #FF0000 (light) or #FF0000 (dark)"
@objc var red: UIColor {
UIColor(named: "red")!
}
/// Color green_alpha_50 is #A000FF00 #A000FF00 or #A000FF00 #A000FF00"
/// Color green_alpha_50 is #A000FF00 (light) or #A000FF00 (dark)"
@objc var green_alpha_50: UIColor {
UIColor(named: "green_alpha_50")!
}
/// Color blue_light_dark is #0000FF #0000FF or #0000AA #0000AA"
/// Color blue_light_dark is #0000FF (light) or #0000AA (dark)"
@objc var blue_light_dark: UIColor {
UIColor(named: "blue_light_dark")!
}
}

View File

@ -1,32 +0,0 @@
// Generated by ResgenSwift.Color 1.2
import UIKit
extension UIhkjhkColorYolo {
/// Color red is #FF0000 #FF0000 or #FF0000 #FF0000"
@objc var red: UIColor {
UIColor(named: "red")!
}
/// Color green_alpha_50 is #A000FF00 #A000FF00 or #A000FF00 #A000FF00"
@objc var green_alpha_50: UIColor {
UIColor(named: "green_alpha_50")!
}
/// Color blue_light_dark is #0000FF #0000FF or #0000AA #0000AA"
@objc var blue_light_dark: UIColor {
UIColor(named: "blue_light_dark")!
}
}

View File

@ -1,7 +1,7 @@
// Generated by ResgenSwift.Analytics 1.2
import MatomoTracker
import FirebaseAnalytics
import Firebase
// MARK: - Protocol
@ -81,7 +81,7 @@ class MatomoAnalyticsManager: AnalyticsManagerProtocol {
class FirebaseAnalyticsManager: AnalyticsManagerProtocol {
func logScreen(name: String, path: String) {
var parameters = [
AnalyticsParameterScreenName: name as NSObject
AnalyticsParameterScreenName: name
]
Analytics.logEvent(
@ -96,25 +96,19 @@ class FirebaseAnalyticsManager: AnalyticsManagerProtocol {
category: String,
params: [String: Any]?
) {
var parameters: [String:NSObject] = [
"action": action as NSObject,
"category": category as NSObject,
var parameters: [String:Any] = [
"action": action,
"category": category,
]
if let supplementaryParameters = params {
for (newKey, newValue) in supplementaryParameters {
if parameters.contains(where: { (key: String, value: NSObject) in
key == newKey
}) {
continue
}
parameters[newKey] = newValue as? NSObject
parameters.merge(supplementaryParameters) { (origin, new) -> Any in
return origin
}
}
Analytics.logEvent(
name.replacingOccurrences(of: [" "], with: "_"),
name,
parameters: parameters
)
}
@ -175,22 +169,19 @@ class AnalyticsManager {
// MARK: - section_one
func logScreenS1DefOne(title: String) {
func logScreenS1DefOne() {
logScreen(
name: "s1 def one \(title)",
path: "s1_def_one/\(title)"
name: "s1 def one",
path: "s1_def_one/"
)
}
func logEventS1DefTwo(title: String, count: String) {
func logEventS1DefTwo() {
logEvent(
name: "s1 def two",
action: "test",
category: "test",
params: [
"title": title,
"count": count
]
params: []
)
}

View File

@ -3,13 +3,9 @@ categories:
- id: section_one
screens:
- id: s1_def_one
name: s1 def one _TITLE_
path: s1_def_one/_TITLE_
tags: ios,droid
parameters:
- name: title
type: String
replaceIn: name,path
name: s1 def one
path: s1_def_one/
tags: ios
events:
- id: s1_def_two
@ -17,11 +13,6 @@ categories:
action: test
category: test
tags: ios
parameters:
- name: title
type: String
- name: count
type: String
- id: section_two
screens:

View File

@ -12,14 +12,14 @@ FORCE_FLAG="$1"
#
#echo "\n-------------------------\n"
#
# Color
swift run -c release ResgenSwift colors $FORCE_FLAG "./Colors/sampleColors1.txt" \
--style all \
--xcassets-path "./Colors/colors.xcassets" \
--extension-output-path "./Colors/Generated/" \
--extension-name "ColorYolo" \
--extension-name-ui-kit "UIColorYolo" \
--extension-suffix "GenAllScript"
## Color
#swift run -c release ResgenSwift colors $FORCE_FLAG "./Colors/sampleColors1.txt" \
# --style all \
# --xcassets-path "./Colors/colors.xcassets" \
# --extension-output-path "./Colors/Generated/" \
# --extension-name "ColorYolo" \
# --extension-name-ui-kit "UIhkjhkColorYolo" \
# --extension-suffix "GenAllScript"
#
#echo "\n-------------------------\n"
#
@ -61,10 +61,10 @@ swift run -c release ResgenSwift colors $FORCE_FLAG "./Colors/sampleColors1.txt"
#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 "ImageYolo" \
# --extension-name-ui-kit "UIImageYolo" \
# --extension-suffix "GenAllScript"
# Images
swift run -c release ResgenSwift images $FORCE_FLAG "./Images/sampleImages.txt" \
--xcassets-path "./Images/imagium.xcassets" \
--extension-output-path "./Images/Generated" \
--extension-name "ImageYolo" \
--extension-name-ui-kit "UIImageYolo" \
--extension-suffix "GenAllScript"

View File

@ -32,15 +32,8 @@ struct Analytics: ParsableCommand {
mutating func run() {
print("[\(Self.toolName)] Starting analytics generation")
print("[\(Self.toolName)] Will use inputFile \(options.inputFile) to generate analytics for target: \(options.target)")
// Check requirements
guard checkRequirements() else { return }
print("[\(Self.toolName)] Will generate analytics")
// Check requirements
guard checkRequirements() else { return }
// Parse input file
let sections = AnalyticsFileParser.parse(options.inputFile, target: options.target)
@ -54,33 +47,20 @@ struct Analytics: ParsableCommand {
print("[\(Self.toolName)] Analytics generated")
}
// MARK: - Requirements
private func checkRequirements() -> Bool {
let fileManager = FileManager()
// Input file
guard fileManager.fileExists(atPath: options.inputFile) else {
let error = AnalyticsError.fileNotExists(options.inputFile)
print(error.description)
Analytics.exit(withError: error)
}
}
guard TrackerType.hasValidTarget(in: options.target) else {
let error = AnalyticsError.noValidTracker(options.target)
print(error.description)
Analytics.exit(withError: error)
}
// Check if needed to regenerate
guard GeneratorChecker.shouldGenerate(force: options.forceGeneration,
inputFilePath: options.inputFile,
extensionFilePath: options.extensionFilePath) else {
print("[\(Self.toolName)] Analytics are already up to date :) ")
return false
}
extension Analytics {
enum TargetType: CaseIterable {
case matomo
case firebase
return true
var value: String {
switch self {
case .matomo:
"matomo"
case .firebase:
"firebase"
}
}
}
}

View File

@ -1,39 +0,0 @@
//
// AnalyticsError.swift
//
//
// Created by Loris Perret on 11/12/2023.
//
import Foundation
enum AnalyticsError: Error {
case noValidTracker(String)
case fileNotExists(String)
case missingElement(String)
case invalidParameter(String)
case parseFailed(String)
case writeFile(String, String)
var description: String {
switch self {
case .noValidTracker(let inputTargets):
return "error: [\(Analytics.toolName)] '\(inputTargets)' ne contient aucun tracker valid"
case .fileNotExists(let filename):
return "error: [\(Analytics.toolName)] File \(filename) does not exists"
case .missingElement(let element):
return "error: [\(Analytics.toolName)] Missing \(element) for Matomo"
case .invalidParameter(let reason):
return "error: [\(Analytics.toolName)] Invalid parameter \(reason)"
case .parseFailed(let baseError):
return "error: [\(Analytics.toolName)] Parse input file failed: \(baseError)"
case .writeFile(let subErrorDescription, let filename):
return "error: [\(Analytics.toolName)] An error occured while writing content to \(filename): \(subErrorDescription)"
}
}
}

View File

@ -10,13 +10,13 @@ import ToolCore
import CoreVideo
class AnalyticsGenerator {
static var targets: [TrackerType] = []
static var targets: [Analytics.TargetType] = []
static func writeExtensionFiles(sections: [AnalyticsCategory], target: String, tags: [String], staticVar: Bool, extensionName: String, extensionFilePath: String) {
// Get target type from enum
let targetsString: [String] = target.components(separatedBy: " ")
TrackerType.allCases.forEach { enumTarget in
Analytics.TargetType.allCases.forEach { enumTarget in
if targetsString.contains(enumTarget.value) {
targets.append(enumTarget)
}
@ -33,9 +33,9 @@ class AnalyticsGenerator {
do {
try extensionFileContent.write(to: extensionFilePathURL, atomically: false, encoding: .utf8)
} catch let error {
let error = AnalyticsError.writeFile(extensionFilePath, error.localizedDescription)
let error = StringiumError.writeFile(extensionFilePath, error.localizedDescription)
print(error.description)
Analytics.exit(withError: error)
Stringium.exit(withError: error)
}
}
@ -58,7 +58,7 @@ class AnalyticsGenerator {
\(Self.getImport())
\(Self.getAnalyticsProtocol())
\(Self.getAnalytics())
// MARK: - Manager
class AnalyticsManager {
@ -91,10 +91,10 @@ class AnalyticsGenerator {
private static func getImport() -> String {
var result: [String] = []
if targets.contains(TrackerType.matomo) {
if targets.contains(Analytics.TargetType.matomo) {
result.append("import MatomoTracker")
}
if targets.contains(TrackerType.firebase) {
if targets.contains(Analytics.TargetType.firebase) {
result.append("import FirebaseAnalytics")
}
@ -136,13 +136,13 @@ class AnalyticsGenerator {
var content: [String] = []
let footer = " }"
if targets.contains(TrackerType.matomo) {
if targets.contains(Analytics.TargetType.matomo) {
header = "func configure(siteId: String, url: String) {"
} else if targets.contains(TrackerType.firebase) {
} else if targets.contains(Analytics.TargetType.firebase) {
header = "func configure() {"
}
if targets.contains(TrackerType.matomo) {
if targets.contains(Analytics.TargetType.matomo) {
content.append("""
managers.append(
MatomoAnalyticsManager(
@ -152,7 +152,7 @@ class AnalyticsGenerator {
)
""")
}
if targets.contains(TrackerType.firebase) {
if targets.contains(Analytics.TargetType.firebase) {
content.append(" managers.append(FirebaseAnalyticsManager())")
}
@ -164,7 +164,7 @@ class AnalyticsGenerator {
.joined(separator: "\n")
}
private static func getAnalyticsProtocol() -> String {
private static func getAnalytics() -> String {
let proto = """
// MARK: - Protocol
@ -182,12 +182,12 @@ class AnalyticsGenerator {
var result: [String] = [proto]
if targets.contains(TrackerType.matomo) {
result.append(MatomoGenerator.service)
if targets.contains(Analytics.TargetType.matomo) {
result.append(MatomoGenerator.service.content)
}
if targets.contains(TrackerType.firebase) {
result.append(FirebaseGenerator.service)
if targets.contains(Analytics.TargetType.firebase) {
result.append(FirebaseGenerator.service.content)
}
return result.joined(separator: "\n")

View File

@ -8,20 +8,19 @@
import Foundation
enum FirebaseGenerator {
static var service: String {
case service
var content: String {
[
FirebaseGenerator.header,
FirebaseGenerator.logScreen,
FirebaseGenerator.logEvent,
FirebaseGenerator.footer
FirebaseGenerator.service.header,
FirebaseGenerator.service.logScreen,
FirebaseGenerator.service.logEvent,
FirebaseGenerator.service.footer
]
.joined(separator: "\n")
}
// MARK: - Private vars
private static var header: String {
private var header: String {
"""
// MARK: - Firebase
@ -29,11 +28,11 @@ enum FirebaseGenerator {
"""
}
private static var logScreen: String {
private var logScreen: String {
"""
func logScreen(name: String, path: String) {
var parameters = [
AnalyticsParameterScreenName: name as NSObject
AnalyticsParameterScreenName: name
]
Analytics.logEvent(
@ -45,7 +44,7 @@ enum FirebaseGenerator {
"""
}
private static var logEvent: String {
private var logEvent: String {
"""
func logEvent(
name: String,
@ -53,32 +52,26 @@ enum FirebaseGenerator {
category: String,
params: [String: Any]?
) {
var parameters: [String:NSObject] = [
"action": action as NSObject,
"category": category as NSObject,
var parameters: [String:Any] = [
"action": action,
"category": category,
]
if let supplementaryParameters = params {
for (newKey, newValue) in supplementaryParameters {
if parameters.contains(where: { (key: String, value: NSObject) in
key == newKey
}) {
continue
}
parameters[newKey] = newValue as? NSObject
parameters.merge(supplementaryParameters) { (origin, new) -> Any in
return origin
}
}
Analytics.logEvent(
name.replacingOccurrences(of: [" "], with: "_"),
name,
parameters: parameters
)
}
"""
}
private static var footer: String {
private var footer: String {
"""
}

View File

@ -8,21 +8,20 @@
import Foundation
enum MatomoGenerator {
static var service: String {
case service
var content: String {
[
MatomoGenerator.header,
MatomoGenerator.setup,
MatomoGenerator.logScreen,
MatomoGenerator.logEvent,
MatomoGenerator.footer
MatomoGenerator.service.header,
MatomoGenerator.service.setup,
MatomoGenerator.service.logScreen,
MatomoGenerator.service.logEvent,
MatomoGenerator.service.footer
]
.joined(separator: "\n")
}
// MARK: - Private vars
private static var header: String {
private var header: String {
"""
// MARK: - Matomo
@ -35,7 +34,7 @@ enum MatomoGenerator {
"""
}
private static var setup: String {
private var setup: String {
"""
// MARK: - Init
@ -64,7 +63,7 @@ enum MatomoGenerator {
"""
}
private static var logScreen: String {
private var logScreen: String {
"""
func logScreen(name: String, path: String) {
guard !tracker.isOptedOut else { return }
@ -80,7 +79,7 @@ enum MatomoGenerator {
"""
}
private static var logEvent: String {
private var logEvent: String {
"""
func logEvent(
name: String,
@ -101,7 +100,7 @@ enum MatomoGenerator {
"""
}
private static var footer: String {
private var footer: String {
"""
}

View File

@ -11,14 +11,10 @@ class AnalyticsCategory {
let id: String // OnBoarding
var definitions = [AnalyticsDefinition]()
// MARK: - Init
init(id: String) {
self.id = id
}
// MARK: - Methods
func hasOneOrMoreMatchingTags(tags: [String]) -> Bool {
let allTags = definitions.flatMap { $0.tags }
let allTagsSet = Set(allTags)

View File

@ -6,7 +6,6 @@
//
import Foundation
import ToolCore
class AnalyticsDefinition {
let id: String
@ -19,16 +18,12 @@ class AnalyticsDefinition {
var parameters: [AnalyticsParameter] = []
var type: TagType
// MARK: - Init
init(id: String, name: String, type: TagType) {
self.id = id
self.name = name
self.type = type
}
// MARK: - Methods
func hasOneOrMoreMatchingTags(inputTags: [String]) -> Bool {
if Set(inputTags).isDisjoint(with: tags) {
return false
@ -36,8 +31,8 @@ class AnalyticsDefinition {
return true
}
// MARK: - Private Methods
// MARK: - Methods
private func getFuncName() -> String {
var pascalCaseTitle: String = ""
id.components(separatedBy: "_").forEach { word in
@ -101,7 +96,7 @@ class AnalyticsDefinition {
supplementaryParams.forEach { param in
params.append("\"\(param.name)\": \(param.name)")
}
if params.count > 1 {
result = """
[
@ -155,3 +150,27 @@ class AnalyticsDefinition {
"""
}
}
extension AnalyticsDefinition {
enum TagType {
case screen
case event
}
}
extension String {
func replacingFirstOccurrence(of: String, with: String) -> Self {
if let range = self.range(of: of) {
let tmp = self.replacingOccurrences(
of: of,
with: with,
options: .literal,
range: range
)
return tmp
}
return self
}
}

View File

@ -17,7 +17,9 @@ struct AnalyticsCategoryDTO: Codable {
var events: [AnalyticsDefinitionEventDTO]?
}
struct AnalyticsDefinitionScreenDTO: Codable {
protocol AnalyticsDefinitionDTO: Codable {}
struct AnalyticsDefinitionScreenDTO: AnalyticsDefinitionDTO {
var id: String
var name: String
var tags: String
@ -27,7 +29,7 @@ struct AnalyticsDefinitionScreenDTO: Codable {
var path: String?
}
struct AnalyticsDefinitionEventDTO: Codable {
struct AnalyticsDefinitionEventDTO: AnalyticsDefinitionDTO {
var id: String
var name: String
var tags: String

View File

@ -12,8 +12,6 @@ class AnalyticsParameter {
var type: String
var replaceIn: [String] = []
// MARK: - Init
init(name: String, type: String) {
self.name = name
self.type = type

View File

@ -1,16 +0,0 @@
//
// TagType.swift
//
//
// Created by Thibaut Schmitt on 08/12/2023.
//
import Foundation
extension AnalyticsDefinition {
enum TagType {
case screen
case event
}
}

View File

@ -1,29 +0,0 @@
//
// TargetType.swift
//
//
// Created by Thibaut Schmitt on 08/12/2023.
//
import Foundation
enum TrackerType: CaseIterable {
case matomo
case firebase
var value: String {
switch self {
case .matomo:
"matomo"
case .firebase:
"firebase"
}
}
static func hasValidTarget(in targets: String) -> Bool {
for tracker in Self.allCases where targets.contains(tracker.value) {
return true
}
return false
}
}

View File

@ -14,49 +14,46 @@ class AnalyticsFileParser {
private static func parseYaml() -> AnalyticsFile {
guard let data = FileManager().contents(atPath: inputFile) else {
let error = AnalyticsError.fileNotExists(inputFile)
print(error.description)
Analytics.exit(withError: error)
let error = GenerateError.fileNotExists(inputFile)
Generate.exit(withError: error)
}
do {
let tagFile = try YAMLDecoder().decode(AnalyticsFile.self, from: data)
return tagFile
} catch {
let error = AnalyticsError.parseFailed(error.localizedDescription)
print(error.description)
Analytics.exit(withError: error)
} catch let error {
Generate.exit(withError: error)
}
}
private static func getParameters(from parameters: [AnalyticsParameterDTO]) -> [AnalyticsParameter] {
parameters.map { dtoParameter in
private static func getParameters(fromData data: [AnalyticsParameterDTO]) -> [AnalyticsParameter] {
var parameters: [AnalyticsParameter] = []
data.forEach { value in
// Type
let type = dtoParameter.type.uppercasedFirst()
let type = value.type.uppercasedFirst()
guard
type == "String" ||
type == "Int" ||
type == "Double" ||
type == "Bool"
else {
let error = AnalyticsError.invalidParameter("type of \(dtoParameter.name)")
print(error.description)
Analytics.exit(withError: error)
let error = GenerateError.invalidParameter("type of \(value.name)")
Generate.exit(withError: error)
}
let parameter = AnalyticsParameter(
name: dtoParameter.name,
type: type
)
if let replaceIn = dtoParameter.replaceIn {
let parameter: AnalyticsParameter = AnalyticsParameter(name: value.name, type: type)
if let replaceIn = value.replaceIn {
parameter.replaceIn = replaceIn.components(separatedBy: ",")
}
return parameter
parameters.append(parameter)
}
return parameters
}
private static func getTagDefinition(
@ -67,24 +64,24 @@ class AnalyticsFileParser {
comments: String?,
parameters: [AnalyticsParameterDTO]?
) -> AnalyticsDefinition {
let definition = AnalyticsDefinition(id: id, name: name, type: type)
definition.tags = tags
.components(separatedBy: ",")
.map { $0.removeLeadingTrailingWhitespace() }
let definition: AnalyticsDefinition = AnalyticsDefinition(id: id, name: name, type: type)
definition.tags = tags.components(separatedBy: ",")
if let comments = comments {
definition.comments = comments
}
if let parameters = parameters {
definition.parameters = Self.getParameters(from: parameters)
definition.parameters = Self.getParameters(fromData: parameters)
}
return definition
}
private static func getTagDefinitionScreen(from screens: [AnalyticsDefinitionScreenDTO]) -> [AnalyticsDefinition] {
screens.map { screen in
private static func getTagDefinitionScreen(fromData screens: [AnalyticsDefinitionScreenDTO]) -> [AnalyticsDefinition] {
var definitions: [AnalyticsDefinition] = []
for screen in screens {
let definition: AnalyticsDefinition = Self.getTagDefinition(
id: screen.id,
name: screen.name,
@ -93,25 +90,28 @@ class AnalyticsFileParser {
comments: screen.comments,
parameters: screen.parameters
)
if target.contains(TrackerType.matomo.value) {
if target.contains(Analytics.TargetType.matomo.value) {
// Path
guard let path = screen.path else {
let error = AnalyticsError.missingElement("screen path")
print(error.description)
Analytics.exit(withError: error)
let error = GenerateError.missingElement("screen path")
Generate.exit(withError: error)
}
definition.path = path
}
return definition
definitions.append(definition)
}
return definitions
}
private static func getTagDefinitionEvent(from events: [AnalyticsDefinitionEventDTO]) -> [AnalyticsDefinition] {
events.map { event in
private static func getTagDefinitionEvent(fromData events: [AnalyticsDefinitionEventDTO]) -> [AnalyticsDefinition] {
var definitions: [AnalyticsDefinition] = []
for event in events {
let definition: AnalyticsDefinition = Self.getTagDefinition(
id: event.id,
name: event.name,
@ -120,59 +120,54 @@ class AnalyticsFileParser {
comments: event.comments,
parameters: event.parameters
)
if target.contains(TrackerType.matomo.value) {
if target.contains(Analytics.TargetType.matomo.value) {
// Category
guard let category = event.category else {
let error = AnalyticsError.missingElement("event category")
print(error.description)
Analytics.exit(withError: error)
let error = GenerateError.missingElement("event category")
Generate.exit(withError: error)
}
definition.category = category
// Action
guard let action = event.action else {
let error = AnalyticsError.missingElement("event action")
print(error.description)
Analytics.exit(withError: error)
let error = GenerateError.missingElement("event action")
Generate.exit(withError: error)
}
definition.action = action
}
return definition
definitions.append(definition)
}
return definitions
}
static func parse(_ inputFile: String, target: String) -> [AnalyticsCategory] {
self.inputFile = inputFile
self.target = target
let tagFile = Self.parseYaml()
let tagFile: AnalyticsFile = Self.parseYaml()
var sections: [AnalyticsCategory] = []
return tagFile
.categories
.map { categorie in
let section: AnalyticsCategory = AnalyticsCategory(id: categorie.id)
if let screens = categorie.screens {
section
.definitions
.append(
contentsOf: Self.getTagDefinitionScreen(from: screens)
)
}
if let events = categorie.events {
section
.definitions
.append(
contentsOf: Self.getTagDefinitionEvent(from: events)
)
}
return section
tagFile.categories.forEach { categorie in
let section: AnalyticsCategory = AnalyticsCategory(id: categorie.id)
if let screens = categorie.screens {
section.definitions.append(contentsOf: Self.getTagDefinitionScreen(fromData: screens))
}
if let events = categorie.events {
section.definitions.append(contentsOf: Self.getTagDefinitionEvent(fromData: events))
}
sections.append(section)
}
return sections
}
}

View File

@ -41,28 +41,12 @@ struct ColorExtensionGenerator {
staticVar: Bool,
extensionName: String,
isSwiftUI: Bool) -> String {
// [
// Self.getHeader(extensionClassname: extensionName, isSwiftUI: isSwiftUI),
// Self.getProperties(for: colors, withStaticVar: staticVar, isSwiftUI: isSwiftUI),
// Self.getFooter()
// ]
// .joined(separator: "\n")
do {
let context: [String: Any] = [
"colors": colors,
"isStatic": staticVar,
"isSwiftUI": isSwiftUI,
"toolName": Colors.toolName,
"resgenVersion": ResgenSwiftVersion,
"extensionClassname": extensionName
]
return try ResgenSwift.environment.renderTemplate(name: "Colors/main_template", context: context)
} catch {
// let error = ColorsToolError.writeExtension(extensionFilePath, error.localizedDescription)
// print(error.description)
Colors.exit(withError: error)
}
[
Self.getHeader(extensionClassname: extensionName, isSwiftUI: isSwiftUI),
Self.getProperties(for: colors, withStaticVar: staticVar, isSwiftUI: isSwiftUI),
Self.getFooter()
]
.joined(separator: "\n")
}
private static func getHeader(extensionClassname: String, isSwiftUI: Bool) -> String {

View File

@ -13,6 +13,11 @@ enum GenerateError: Error {
case commandError([String], String)
case writeFile(String, String)
// Analytics
case missingElement(String)
case invalidParameter(String)
var description: String {
switch self {
case .fileNotExists(let filename):
@ -29,6 +34,12 @@ enum GenerateError: Error {
case .writeFile(let filename, let info):
return "error: [\(Generate.toolName)] An error occured while writing file in \(filename): \(info)"
case .missingElement(let element):
return "error: [\(Generate.toolName)] Missing \(element) for Matomo"
case .invalidParameter(let reason):
return "error: [\(Generate.toolName)] Invalid parameter \(reason)"
}
}
}

View File

@ -8,8 +8,6 @@
import ToolCore
import Foundation
import ArgumentParser
import Stencil
import PathKit
struct ResgenSwift: ParsableCommand {
@ -34,20 +32,6 @@ struct ResgenSwift: ParsableCommand {
// subcommand is not given on the command line.
//defaultSubcommand: Twine.self
)
static let projectDirectory = URL(fileURLWithPath: #file) // ProjectDir/Sources/ResgenSwift/main.swift
.deletingLastPathComponent() // ProjectDir/Sources/ResgenSwift/
.deletingLastPathComponent() // ProjectDir/Sources/
.deletingLastPathComponent() // ProjectDir/
static let environment = Environment(
loader: FileSystemLoader(
paths: [
Path("\(projectDirectory.path)/Templates/")
]
)
)
}
print(ResgenSwift.projectDirectory.path)
ResgenSwift.main()

View File

@ -63,7 +63,7 @@ public extension String {
replacingOccurrences(of: "~", with: "\(FileManager.default.homeDirectoryForCurrentUser.relativePath)")
}
func colorComponent() -> (alpha: String, red: String, green: String, blue: String) {
func colorComponent() -> (alpha: String, red: String, green: String, blue: String) {
var alpha: String = "FF"
var red: String
var green: String
@ -89,19 +89,4 @@ public extension String {
func uppercasedFirst() -> String {
prefix(1).uppercased() + dropFirst()
}
func replacingFirstOccurrence(of: String, with: String) -> Self {
if let range = self.range(of: of) {
let tmp = self.replacingOccurrences(
of: of,
with: with,
options: .literal,
range: range
)
return tmp
}
return self
}
}

View File

@ -1,21 +0,0 @@
// Generated by ResgenSwift.{{ toolName }} {{ resgenVersion }}
{% if isSwiftUI %}
import SwiftUI
{% else %}
import UIKit
{% endif %}
extension {{ extensionClassname }} {
{% for color in colors %}
{% if isSwiftUI %}
/// Color {{ color.name }} is {{ color.light }} {{ color.light }} or {{ color.dark }} {{ color.dark }}"
{% if isStatic %}static {% endif %}var {{ color.name }}: Color {
Color("{{ color.name }}")
}
{% else %}
/// Color {{ color.name }} is {{ color.light }} {{ color.light }} or {{ color.dark }} {{ color.dark }}"
{% if isStatic %}static {% else %}@objc {% endif %}var {{ color.name }}: UIColor {
UIColor(named: "{{ color.name }}")!
}
{% endif %}
{% endfor %}
}

View File

@ -1,4 +0,0 @@
/// Color {{ color.name }} is {{ color.light }} {{ color.light }} or {{ color.dark }} {{ color.dark }}"
{% if isStatic %}static {% endif %}var {{ color.name }}: Color {
Color("{{ color.name }}")
}

View File

@ -1,4 +0,0 @@
/// Color {{ color.name }} is {{ color.light }} {{ color.light }} or {{ color.dark }} {{ color.dark }}"
{% if isStatic %}static {% else %}@objc {% endif %}var {{ color.name }}: UIColor {
UIColor(named: "{{ color.name }}")!
}

View File

@ -51,7 +51,7 @@ final class AnalyticsGeneratorTests: XCTestCase {
]
// When
AnalyticsGenerator.targets = [TrackerType.firebase]
AnalyticsGenerator.targets = [Analytics.TargetType.firebase]
let extensionContent = AnalyticsGenerator.getExtensionContent(sections: [sectionOne, sectionTwo, sectionThree],
tags: ["ios", "iosonly"],
staticVar: false,
@ -216,7 +216,7 @@ final class AnalyticsGeneratorTests: XCTestCase {
]
// When
AnalyticsGenerator.targets = [TrackerType.matomo]
AnalyticsGenerator.targets = [Analytics.TargetType.matomo]
let extensionContent = AnalyticsGenerator.getExtensionContent(sections: [sectionOne, sectionTwo, sectionThree],
tags: ["ios", "iosonly"],
staticVar: false,
@ -409,7 +409,7 @@ final class AnalyticsGeneratorTests: XCTestCase {
]
// When
AnalyticsGenerator.targets = [TrackerType.matomo, TrackerType.firebase]
AnalyticsGenerator.targets = [Analytics.TargetType.matomo, Analytics.TargetType.firebase]
let extensionContent = AnalyticsGenerator.getExtensionContent(sections: [sectionOne, sectionTwo, sectionThree],
tags: ["ios", "iosonly"],
staticVar: false,

View File

@ -1,5 +1,5 @@
//
// DiffString.swift
// File.swift
//
//
// Created by Loris Perret on 06/12/2023.
@ -7,6 +7,7 @@
import Foundation
/// Find first differing character between two strings
///
/// :param: s1 First String