22 Commits
2.2.0 ... 2.2.5

Author SHA1 Message Date
fdd23f4378 Fixing tests again
All checks were successful
openium/resgen.swift/pipeline/head This commit is unstable
2026-01-21 15:20:08 +01:00
8d37744373 Fixing tests
Some checks failed
openium/resgen.swift/pipeline/head There was a failure building this commit
2026-01-21 11:53:33 +01:00
b9aac55a76 Add new analytics parameters pathSuffix
Some checks failed
openium/resgen.swift/pipeline/head There was a failure building this commit
2026-01-21 11:39:46 +01:00
7bbb702861 Add missing Sendable inheritance for architecture subclass
All checks were successful
openium/resgen.swift/pipeline/head This commit looks good
2026-01-12 11:39:02 +01:00
0118492162 Add MainActor on AnalysticsManager shared property (#24)
All checks were successful
openium/resgen.swift/pipeline/head This commit looks good
Reviewed-on: #24
2026-01-05 14:31:39 +01:00
6debae8162 Merge pull request 'fix/RES-75_Multiligne' (#23) from fix/RES-75_Multiligne into master
All checks were successful
openium/resgen.swift/pipeline/head This commit is unstable
Reviewed-on: #23
2025-11-18 10:04:01 +01:00
434d427136 fix test
All checks were successful
openium/resgen.swift/pipeline/pr-master This commit is unstable
2025-11-10 17:19:13 +01:00
052f416741 Update jenkinsFile
Some checks failed
openium/resgen.swift/pipeline/pr-master There was a failure building this commit
2025-11-10 16:01:10 +01:00
4b944ed8c7 RES-75 Ajouter un pretty print pour le dictionnaire des params
Some checks failed
openium/resgen.swift/pipeline/pr-master There was a failure building this commit
openium/resgen.swift/pipeline/head There was a failure building this commit
2025-10-29 11:07:37 +01:00
1f9af76b40 RES-74 Ajout du multiligne sur les logs des analytics
Some checks failed
openium/resgen.swift/pipeline/head There was a failure building this commit
2025-10-29 09:23:10 +01:00
7247d20ae4 Merge pull request 'feat/RES-73_Ajout_DebugMode_Analytics' (#22) from feat/RES-73_Ajout_DebugMode_Analytics into master
Some checks failed
openium/resgen.swift/pipeline/head There was a failure building this commit
Reviewed-on: #22
2025-10-21 15:03:05 +02:00
63404f8f20 Ajout de maj
Some checks are pending
openium/resgen.swift/pipeline/pr-master Build started...
2025-10-21 15:02:34 +02:00
c4a3aa54d6 Gestion du cas des strings vides
Some checks failed
openium/resgen.swift/pipeline/pr-master There was a failure building this commit
2025-10-21 10:57:20 +02:00
b9e610a6d9 Review
Some checks failed
openium/resgen.swift/pipeline/pr-master There was a failure building this commit
2025-10-20 17:08:08 +02:00
7c6a8d2ac3 Génération du fichier + suppression variable inutile
Some checks failed
openium/resgen.swift/pipeline/pr-master There was a failure building this commit
openium/resgen.swift/pipeline/head There was a failure building this commit
2025-10-20 16:33:47 +02:00
f0aac3a91b RES-73 Ajout d'un debugMode iOS
Some checks failed
openium/resgen.swift/pipeline/head There was a failure building this commit
2025-10-20 16:30:36 +02:00
f1ca8e92b7 Remove unwanted lang translation when generated xcStrings catalog
All checks were successful
openium/resgen.swift/pipeline/head This commit looks good
2025-09-30 16:08:45 +02:00
Jean-Charles Neboit
436bc4b2af Fix Makefile INSTALL_DIR & man page
All checks were successful
gitea-openium/resgen.swift/pipeline/pr-master This commit looks good
gitea-openium/resgen.swift/pipeline/head This commit looks good
2025-09-11 14:28:21 +02:00
e0e561ff7f Update SwiftLint and fix some Swift 6 issues
All checks were successful
gitea-openium/resgen.swift/pipeline/head This commit looks good
2025-09-10 16:51:23 +02:00
ed4e9849e7 fix(RES-71): Checkstyle resgen analytics (#20)
All checks were successful
gitea-openium/resgen.swift/pipeline/head This commit looks good
Reviewed-on: #20
Reviewed-by: Thibaut Schmitt <t.schmitt@openium.fr>
Co-authored-by: Quentin Bandera <q.bandera@openium.fr>
Co-committed-by: Quentin Bandera <q.bandera@openium.fr>
2025-08-26 08:51:33 +02:00
ddf1d2509f Fix d'une inversion de property dans la génération des strings
All checks were successful
gitea-openium/resgen.swift/pipeline/head This commit looks good
2025-08-26 08:50:45 +02:00
2ae06867c7 Handle backslash in xcstrings file generation
All checks were successful
gitea-openium/resgen.swift/pipeline/head This commit looks good
2025-08-04 10:38:45 +02:00
38 changed files with 901 additions and 580 deletions

2
Jenkinsfile vendored
View File

@@ -1,6 +1,6 @@
library "openiumpipeline" library "openiumpipeline"
env.DEVELOPER_DIR="/Applications/Xcode-16.3.0.app/Contents/Developer" env.DEVELOPER_DIR="/Applications/Xcode-26.2.0.app/Contents/Developer"
// env.SIMULATOR_DEVICE_TYPES="iPhone-14-Pro" // env.SIMULATOR_DEVICE_TYPES="iPhone-14-Pro"
// env.SLACK_CHANNEL = "prj-skdevkit" // env.SLACK_CHANNEL = "prj-skdevkit"
env.IS_PACKAGE_SWIFT=1 env.IS_PACKAGE_SWIFT=1

View File

@@ -1,7 +1,6 @@
SHELL = /bin/zsh SHELL = /bin/zsh
#INSTALL_DIR ?= /usr/local/bin INSTALL_DIR = /usr/local/bin
INSTALL_DIR = /tmp/ResgenYolo
MAN_DIR := /usr/local/share/man MAN_DIR := /usr/local/share/man
MAN_PAGE_NAME = resgen-swift.1 MAN_PAGE_NAME = resgen-swift.1
@@ -14,7 +13,7 @@ BUILD_DIR = $(REPO_DIR)/.build
# create-man-files: # create-man-files:
# swift package plugin generate-manual # swift package plugin generate-manual
# cp $(BUILDDIR)/plugins/GenerateManualPlugin/outputs/ResgenSwift/resgen-swift.1 $(REPODIR)/man/resgen-swift.1 # cp $(BUILDDIR)/plugins/GenerateManual/outputs/ResgenSwift/resgen-swift.1 $(REPODIR)/man/resgen-swift.1
# install-man-files: # install-man-files:
# mkdir -p ${DESTDIR}${mandir}/man1 # mkdir -p ${DESTDIR}${mandir}/man1
@@ -23,7 +22,7 @@ BUILD_DIR = $(REPO_DIR)/.build
create-and-install-man-files: create-and-install-man-files:
swift package plugin generate-manual swift package plugin generate-manual
mkdir -p ${MAN_DIR}/man1 mkdir -p ${MAN_DIR}/man1
cp $(BUILD_DIR)/plugins/GenerateManualPlugin/outputs/ResgenSwift/${MAN_PAGE_NAME} ${MAN_DIR}/man1/${MAN_PAGE_NAME} cp $(BUILD_DIR)/plugins/GenerateManual/outputs/ResgenSwift/${MAN_PAGE_NAME} ${MAN_DIR}/man1/${MAN_PAGE_NAME}
# #
# Build and install # Build and install

View File

@@ -1,4 +1,5 @@
{ {
"originHash" : "fae67d9ce14b6664edc4151ad1a55b74d50d7281499f09eeca50b0376d0f837f",
"pins" : [ "pins" : [
{ {
"identity" : "swift-argument-parser", "identity" : "swift-argument-parser",
@@ -14,8 +15,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/lukepistrol/SwiftLintPlugin", "location" : "https://github.com/lukepistrol/SwiftLintPlugin",
"state" : { "state" : {
"revision" : "87454f5c9ff4d644086aec2a0df1ffba678e7f3c", "revision" : "8e785a9801fc7961fef3d41ccb81acb3bd3d9735",
"version" : "0.57.1" "version" : "0.60.0"
} }
}, },
{ {
@@ -28,5 +29,5 @@
} }
} }
], ],
"version" : 2 "version" : 3
} }

View File

@@ -1,4 +1,4 @@
// swift-tools-version:5.9 // swift-tools-version:6.1
// The swift-tools-version declares the minimum version of Swift required to build this package. // The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription import PackageDescription
@@ -18,7 +18,7 @@ let package = Package(
), ),
.package( .package(
url: "https://github.com/lukepistrol/SwiftLintPlugin", url: "https://github.com/lukepistrol/SwiftLintPlugin",
exact: "0.57.1" exact: "0.60.0"
), ),
], ],
targets: [ targets: [

View File

@@ -6,16 +6,16 @@ extension ColorYolo {
/// Color red is #FF0000 (light) or #FF0000 (dark)" /// Color red is #FF0000 (light) or #FF0000 (dark)"
public var red: Color { public var red: Color {
Color("red") Color("red", bundle: Bundle.main)
} }
/// Color green_alpha_50 is #A000FF00 (light) or #A000FF00 (dark)" /// Color green_alpha_50 is #A000FF00 (light) or #A000FF00 (dark)"
public var green_alpha_50: Color { public var green_alpha_50: Color {
Color("green_alpha_50") Color("green_alpha_50", bundle: Bundle.main)
} }
/// Color blue_light_dark is #0000FF (light) or #0000AA (dark)" /// Color blue_light_dark is #0000FF (light) or #0000AA (dark)"
public var blue_light_dark: Color { public var blue_light_dark: Color {
Color("blue_light_dark") Color("blue_light_dark", bundle: Bundle.main)
} }
} }

View File

@@ -6,16 +6,16 @@ extension UIColorYolo {
/// Color red is #FF0000 (light) or #FF0000 (dark)" /// Color red is #FF0000 (light) or #FF0000 (dark)"
@objc public var red: UIColor { @objc public var red: UIColor {
UIColor(named: "red")! UIColor(named: "red", in: Bundle.main, compatibleWith: nil)!
} }
/// Color green_alpha_50 is #A000FF00 (light) or #A000FF00 (dark)" /// Color green_alpha_50 is #A000FF00 (light) or #A000FF00 (dark)"
@objc public var green_alpha_50: UIColor { @objc public var green_alpha_50: UIColor {
UIColor(named: "green_alpha_50")! UIColor(named: "green_alpha_50", in: Bundle.main, compatibleWith: nil)!
} }
/// Color blue_light_dark is #0000FF (light) or #0000AA (dark)" /// Color blue_light_dark is #0000FF (light) or #0000AA (dark)"
@objc public var blue_light_dark: UIColor { @objc public var blue_light_dark: UIColor {
UIColor(named: "blue_light_dark")! UIColor(named: "blue_light_dark", in: Bundle.main, compatibleWith: nil)!
} }
} }

View File

@@ -6,26 +6,26 @@ import SwiftUI
extension ImageYolo { extension ImageYolo {
public var article_notification_pull_detail: Image { public var article_notification_pull_detail: Image {
Image("article_notification_pull_detail") Image("article_notification_pull_detail", bundle: Bundle.main)
} }
public var article_notification_pull: Image { public var article_notification_pull: Image {
Image("article_notification_pull") Image("article_notification_pull", bundle: Bundle.main)
} }
public var new_article: Image { public var new_article: Image {
Image("new_article") Image("new_article", bundle: Bundle.main)
} }
public var welcome_background: Image { public var welcome_background: Image {
Image("welcome_background") Image("welcome_background", bundle: Bundle.main)
} }
public var article_trash: Image { public var article_trash: Image {
Image("article_trash") Image("article_trash", bundle: Bundle.main)
} }
public var ic_close_article: Image { public var ic_close_article: Image {
Image("ic_close_article") Image("ic_close_article", bundle: Bundle.main)
} }
} }

View File

@@ -6,26 +6,26 @@ import UIKit
extension UIImageYolo { extension UIImageYolo {
public var article_notification_pull_detail: UIImage { public var article_notification_pull_detail: UIImage {
UIImage(named: "article_notification_pull_detail")! UIImage(named: "article_notification_pull_detail", in: Bundle.main, with: nil)!
} }
public var article_notification_pull: UIImage { public var article_notification_pull: UIImage {
UIImage(named: "article_notification_pull")! UIImage(named: "article_notification_pull", in: Bundle.main, with: nil)!
} }
public var new_article: UIImage { public var new_article: UIImage {
UIImage(named: "new_article")! UIImage(named: "new_article", in: Bundle.main, with: nil)!
} }
public var welcome_background: UIImage { public var welcome_background: UIImage {
UIImage(named: "welcome_background")! UIImage(named: "welcome_background", in: Bundle.main, with: nil)!
} }
public var article_trash: UIImage { public var article_trash: UIImage {
UIImage(named: "article_trash")! UIImage(named: "article_trash", in: Bundle.main, with: nil)!
} }
public var ic_close_article: UIImage { public var ic_close_article: UIImage {
UIImage(named: "ic_close_article")! UIImage(named: "ic_close_article", in: Bundle.main, with: nil)!
} }
} }

View File

@@ -49,12 +49,12 @@ extension String {
} }
/// Translation in en : /// Translation in en :
/// Loading data... /// Loading\ndata...
/// ///
/// Comment : /// Comment :
/// No comment /// No comment
public var generic_loading_data: String { public var generic_loading_data: String {
NSLocalizedString("generic_loading_data", tableName: kStringsFileName, bundle: Bundle.main, value: "Loading data...", comment: "") NSLocalizedString("generic_loading_data", tableName: kStringsFileName, bundle: Bundle.main, value: "Loading\ndata...", comment: "")
} }
/// Translation in en : /// Translation in en :

View File

@@ -32,19 +32,19 @@
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Loading data..." "value" : "Loading\ndata..."
} }
}, },
"en-us" : { "en-us" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Loading data..." "value" : "Loading\ndata..."
} }
}, },
"fr" : { "fr" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Chargement des données..." "value" : "Chargement\ndes données..."
} }
} }
} }
@@ -56,19 +56,19 @@
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Welcome \\\"%@\\\" !" "value" : "Welcome \"%@\" !"
} }
}, },
"en-us" : { "en-us" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Welcome \\\"%@\\\" !" "value" : "Welcome \"%@\" !"
} }
}, },
"fr" : { "fr" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Bienvenue \\\"%@\\\" !" "value" : "Bienvenue \"%@\" !"
} }
} }
} }

View File

@@ -14,11 +14,11 @@
fr = Retour fr = Retour
en-us = Back en-us = Back
[generic_loading_data] [generic_loading_data]
en = Loading data... en = Loading\ndata...
tags = droid,ios tags = droid,ios
comments = comments =
fr = Chargement des données... fr = Chargement\ndes données...
en-us = Loading data... en-us = Loading\ndata...
[generic_welcome_firstname_format] [generic_welcome_firstname_format]
en = Welcome "%@" ! en = Welcome "%@" !
tags = droid,ios tags = droid,ios

View File

@@ -3,10 +3,11 @@
import Foundation import Foundation
import MatomoTracker import MatomoTracker
import FirebaseAnalytics import FirebaseAnalytics
import os
// MARK: - Protocol // MARK: - Protocol
public protocol AnalyticsManagerProtocol { internal protocol AnalyticsManagerProtocol {
func logScreen( func logScreen(
name: String, name: String,
@@ -63,7 +64,7 @@ class MatomoAnalyticsManager: AnalyticsManagerProtocol {
) { ) {
guard let trackerUrl = tracker.contentBase?.absoluteString else { return } guard let trackerUrl = tracker.contentBase?.absoluteString else { return }
let urlString = URL(string: "\(trackerUrl)" + "/" + "\(path)" + "iOS") let urlString = URL(string: "\(trackerUrl)" + "/" + "\(path)" + "/yolo")
tracker.track( tracker.track(
view: [name], view: [name],
url: urlString url: urlString
@@ -106,7 +107,7 @@ class FirebaseAnalyticsManager: AnalyticsManagerProtocol {
] ]
if path.isEmpty == false { if path.isEmpty == false {
parameters["path"] = path + "/iOS" as NSObject parameters["path"] = path + "/yolo" as NSObject
} }
if let supplementaryParameters = params { if let supplementaryParameters = params {
@@ -170,7 +171,7 @@ class FirebaseAnalyticsManager: AnalyticsManagerProtocol {
// MARK: - Traker Type // MARK: - Traker Type
public enum TrackerType: CaseIterable { internal enum TrackerType: CaseIterable {
case matomo case matomo
case firebase case firebase
@@ -178,9 +179,10 @@ public enum TrackerType: CaseIterable {
// MARK: - Manager // MARK: - Manager
public class AnalyticsManager { internal class AnalyticsManager {
public static var shared = AnalyticsManager() @MainActor
internal static var shared = AnalyticsManager()
private init() {} private init() {}
@@ -188,6 +190,8 @@ public class AnalyticsManager {
var managers: [TrackerType: AnalyticsManagerProtocol] = [:] var managers: [TrackerType: AnalyticsManagerProtocol] = [:]
private var isDebugMode: Bool = false
private var isEnabled: Bool { private var isEnabled: Bool {
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" { if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
false false
@@ -196,6 +200,8 @@ public class AnalyticsManager {
} }
} }
private let logger = Logger(subsystem: "resgen", category: "analytics")
// MARK: - Enable Methods // MARK: - Enable Methods
private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) { private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) {
@@ -208,15 +214,16 @@ public class AnalyticsManager {
} }
} }
public func enableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) { internal func enableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
setAnalytics(enable: true, analytics) setAnalytics(enable: true, analytics)
} }
public func disableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) { internal func disableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
setAnalytics(enable: false, analytics) setAnalytics(enable: false, analytics)
} }
public func configure(siteId: String, url: String) { internal func configure(siteId: String, url: String, isDebugMode: Bool = false) {
self.isDebugMode = isDebugMode
managers[TrackerType.matomo] = MatomoAnalyticsManager( managers[TrackerType.matomo] = MatomoAnalyticsManager(
siteId: siteId, siteId: siteId,
url: url url: url
@@ -226,14 +233,40 @@ public class AnalyticsManager {
// MARK: - Private Log Methods // MARK: - Private Log Methods
private func formattedParams(_ params: [String: Any]?) -> String {
guard let params = params, !params.isEmpty else { return "-" }
let formattedParams = params.map { key, value in
" \(key): \(value)"
}
.joined(separator: "\n")
return "\n" + formattedParams
}
private func logScreen( private func logScreen(
name: String, name: String,
path: String, path: String,
params: [String: Any]? params: [String: Any]?
) { ) {
guard isEnabled else { return } guard isEnabled else {
if isDebugMode {
logger.log("Analytics disabled")
}
return
}
managers.values.forEach { manager in managers.values.forEach { manager in
if isDebugMode {
logger.debug("""
🖥️ Screen:
Name: \(name, privacy: .public)
Path: \(path, privacy: .public)
Params: \(self.formattedParams(params), privacy: .public)
""")
}
manager.logScreen( manager.logScreen(
name: name, name: name,
path: path, path: path,
@@ -248,9 +281,25 @@ public class AnalyticsManager {
category: String, category: String,
params: [String: Any]? params: [String: Any]?
) { ) {
guard isEnabled else { return } guard isEnabled else {
if isDebugMode {
logger.log("Analytics disabled")
}
return
}
managers.values.forEach { manager in managers.values.forEach { manager in
if isDebugMode {
logger.debug("""
📊 Event:
Name: \(name, privacy: .public)
Action: \(action.isEmpty ? "-" : action, privacy: .public)
Category: \(category.isEmpty ? "-" : category, privacy: .public)
Params: \(self.formattedParams(params), privacy: .public)
""")
}
manager.logEvent( manager.logEvent(
name: name, name: name,
action: action, action: action,
@@ -262,7 +311,7 @@ public class AnalyticsManager {
// MARK: - section_one // MARK: - section_one
public func logScreenS1DefOne(title: String) { internal func logScreenS1DefOne(title: String) {
logScreen( logScreen(
name: "s1 def one \(title)", name: "s1 def one \(title)",
path: "s1_def_one/\(title)", path: "s1_def_one/\(title)",
@@ -270,7 +319,7 @@ public class AnalyticsManager {
) )
} }
public func logEventS1DefTwo( internal func logEventS1DefTwo(
title: String, title: String,
count: String, count: String,
test2: String = "test" test2: String = "test"
@@ -290,10 +339,10 @@ public class AnalyticsManager {
// MARK: - section_two // MARK: - section_two
public func logScreenS2DefOne() { internal func logScreenS2DefOne() {
logScreen( logScreen(
name: "s2 def one", name: "s2 def one",
path: "s2_def_one/", path: "s2_def_one",
params: nil params: nil
) )
} }

29
SampleFiles/Tags/R.swift Normal file
View File

@@ -0,0 +1,29 @@
// Generated by ResgenSwift.Generate 2.2.0
class R: Sendable {
static let images = R2Image()
static let strings = R2String()
static let fonts = R2Font()
static let images = R2Image()
static let ui = R2UI()
}
final class R2Image: Sendable {}
final class R2String: Sendable {}
final class R2Font: Sendable {}
final class R2Image: Sendable {}
class R2UI: Sendable {
let images = R2UIImage()
let fonts = R2UIFont()
let images = R2UIImage()
}
final class R2UIImage: Sendable {}
final class R2UIFont: Sendable {}
final class R2UIImage: Sendable {}

View File

@@ -33,7 +33,7 @@ categories:
screens: screens:
- id: s2_def_one - id: s2_def_one
name: s2 def one name: s2 def one
path: s2_def_one/ path: s2_def_one///
tags: ios tags: ios
events: events:

View File

@@ -3,69 +3,67 @@
FORCE_FLAG="$1" FORCE_FLAG="$1"
## Font ## Font
swift run -c release ResgenSwift fonts $FORCE_FLAG "./Fonts/sampleFontsAll.txt" \ #swift run -c release ResgenSwift fonts $FORCE_FLAG "./Fonts/sampleFontsAll.txt" \
--extension-output-path "./Fonts/Generated" \ # --extension-output-path "./Fonts/Generated" \
--extension-name "FontYolo" \ # --extension-name "FontYolo" \
--extension-name-ui-kit "UIFontYolo" \ # --extension-name-ui-kit "UIFontYolo" \
--extension-suffix "GenAllScript" \ # --extension-suffix "GenAllScript" \
--info-plist-paths "./Fonts/Generated/test.plist ./Fonts/Generated/test2.plist" # --info-plist-paths "./Fonts/Generated/test.plist ./Fonts/Generated/test2.plist"
#
echo "\n-------------------------\n" #echo "\n-------------------------\n"
#
## Color ### Color
swift run -c release ResgenSwift colors $FORCE_FLAG "./Colors/sampleColors1.txt" \ #swift run -c release ResgenSwift colors $FORCE_FLAG "./Colors/sampleColors1.txt" \
--style all \ # --style all \
--xcassets-path "./Colors/colors.xcassets" \ # --xcassets-path "./Colors/colors.xcassets" \
--extension-output-path "./Colors/Generated/" \ # --extension-output-path "./Colors/Generated/" \
--extension-name "ColorYolo" \ # --extension-name "ColorYolo" \
--extension-name-ui-kit "UIhkjhkColorYolo" \ # --extension-name-ui-kit "UIhkjhkColorYolo" \
--extension-suffix "GenAllScript" # --extension-suffix "GenAllScript"
#
echo "\n-------------------------\n" #echo "\n-------------------------\n"
#
## Twine ### Twine
swift run -c release ResgenSwift strings twine $FORCE_FLAG "./Twine/sampleStrings.txt" \ #swift run -c release ResgenSwift strings twine $FORCE_FLAG "./Twine/sampleStrings.txt" \
--output-path "./Twine/Generated" \ # --output-path "./Twine/Generated" \
--langs "fr en en-us" \ # --langs "fr en en-us" \
--default-lang "en" \ # --default-lang "en" \
--extension-output-path "./Twine/Generated" # --extension-output-path "./Twine/Generated"
#
echo "\n-------------------------\n" #echo "\n-------------------------\n"
## Strings ## Strings
swift run -c release ResgenSwift strings stringium $FORCE_FLAG "./Strings/sampleStrings.txt" \ #swift run -c release ResgenSwift strings stringium $FORCE_FLAG "./Strings/sampleStrings.txt" \
--output-path "./Strings/Generated" \ # --output-path "./Strings/Generated" \
--langs "fr en en-us" \ # --langs "fr en en-us" \
--default-lang "en" \ # --default-lang "en" \
--extension-output-path "./Strings/Generated" \ # --extension-output-path "./Strings/Generated" \
--extension-name "String" \ # --extension-name "String" \
--extension-suffix "GenAllScript" # --extension-suffix "GenAllScript"
echo "\n-------------------------\n" #echo "\n-------------------------\n"
#
## Tags ### Tags
swift run -c release ResgenSwift strings tags $FORCE_FLAG "./Tags/sampleTags.txt" \ #swift run -c release ResgenSwift strings tags $FORCE_FLAG "./Tags/sampleTags.txt" \
--lang "ium" \ # --lang "ium" \
--extension-output-path "./Tags/Generated" \ # --extension-output-path "./Tags/Generated" \
--extension-name "Tags" \ # --extension-name "Tags" \
--extension-suffix "GenAllScript" # --extension-suffix "GenAllScript"
#
echo "\n-------------------------\n" #echo "\n-------------------------\n"
#
# Analytics ## Analytics
swift run -c release ResgenSwift analytics $FORCE_FLAG "./Tags/sampleTags.yml" \ swift run -c release ResgenSwift analytics -f "./Tags/sampleTags.yml" \
--target "firebase" \ --target "firebase matomo" \
--extension-output-path "./Tags/Generated" \ --output-file "./Tags/Generated/Analytics+GenAllScript.swift" \
--extension-name "Analytics" \ --path-suffix "sampleApp"
--extension-suffix "GenAllScript" \ #
--static-members true #echo "\n-------------------------\n"
#
echo "\n-------------------------\n" ### Images
#swift run -c release ResgenSwift images $FORCE_FLAG "./Images/sampleImages.txt" \
## Images # --xcassets-path "./Images/imagium.xcassets" \
swift run -c release ResgenSwift images $FORCE_FLAG "./Images/sampleImages.txt" \ # --extension-output-path "./Images/Generated" \
--xcassets-path "./Images/imagium.xcassets" \ # --extension-name "ImageYolo" \
--extension-output-path "./Images/Generated" \ # --extension-name-ui-kit "UIImageYolo" \
--extension-name "ImageYolo" \ # --extension-suffix "GenAllScript"
--extension-name-ui-kit "UIImageYolo" \
--extension-suffix "GenAllScript"

View File

@@ -90,7 +90,8 @@ analytics:
inputFile: ./Tags/sampleTags.yml inputFile: ./Tags/sampleTags.yml
target: "matomo firebase" target: "matomo firebase"
outputFile: ./Tags/Generated/Analytics+GenAllScript.swift outputFile: ./Tags/Generated/Analytics+GenAllScript.swift
visibility: public visibility: internal
pathSuffix: "yolo"
# #

View File

@@ -13,7 +13,7 @@ struct Analytics: ParsableCommand {
// MARK: - Command Configuration // MARK: - Command Configuration
static var configuration = CommandConfiguration( static let configuration = CommandConfiguration(
abstract: "Generate analytics extension file.", abstract: "Generate analytics extension file.",
version: ResgenSwiftVersion version: ResgenSwiftVersion
) )
@@ -38,11 +38,11 @@ struct Analytics: ParsableCommand {
print("[\(Self.toolName)] Will generate analytics") print("[\(Self.toolName)] Will generate analytics")
// Check requirements
guard checkRequirements() else { return }
// Parse input file // Parse input file
let sections = AnalyticsFileParser().parse(options.inputFile, target: options.target) let sections = AnalyticsFileParser().parse(
options.inputFile,
target: options.target
)
// Generate extension // Generate extension
AnalyticsGenerator.writeExtensionFiles( AnalyticsGenerator.writeExtensionFiles(
@@ -51,7 +51,8 @@ struct Analytics: ParsableCommand {
tags: ["ios", "iosonly"], tags: ["ios", "iosonly"],
isStatic: options.staticMembers, isStatic: options.staticMembers,
outputFile: options.outputFile, outputFile: options.outputFile,
visibility: options.extensionVisibility visibility: options.extensionVisibility,
pathSuffix: options.pathSuffix
) )
print("[\(Self.toolName)] Analytics generated") print("[\(Self.toolName)] Analytics generated")

View File

@@ -44,4 +44,9 @@ struct AnalyticsOptions: ParsableArguments {
completion: .list(["public", "private", "package", "internal"]) completion: .list(["public", "private", "package", "internal"])
) )
var extensionVisibility: ExtensionVisibility = .internal var extensionVisibility: ExtensionVisibility = .internal
@Option(
help: "Suffix to add to every path parameters. Default is 'iOS'."
)
var pathSuffix: String = "iOS"
} }

View File

@@ -24,7 +24,8 @@ enum AnalyticsGenerator {
tags: [String], tags: [String],
isStatic: Bool, isStatic: Bool,
outputFile: String, outputFile: String,
visibility: ExtensionVisibility visibility: ExtensionVisibility,
pathSuffix: String
) { ) {
// Get target type from enum // Get target type from enum
let targetsString: [String] = target.components(separatedBy: " ") let targetsString: [String] = target.components(separatedBy: " ")
@@ -44,7 +45,8 @@ enum AnalyticsGenerator {
sections: sections, sections: sections,
tags: tags, tags: tags,
isStatic: isStatic, isStatic: isStatic,
visibility: visibility visibility: visibility,
pathSuffix: pathSuffix
) )
// Write content // Write content
@@ -65,13 +67,15 @@ enum AnalyticsGenerator {
sections: [AnalyticsCategory], sections: [AnalyticsCategory],
tags: [String], tags: [String],
isStatic: Bool, isStatic: Bool,
visibility: ExtensionVisibility visibility: ExtensionVisibility,
pathSuffix: String
) -> String { ) -> String {
[ [
getHeader( getHeader(
targets: targets, targets: targets,
isStatic: isStatic, isStatic: isStatic,
visibility: visibility visibility: visibility,
pathSuffix: pathSuffix
), ),
getProperties( getProperties(
sections: sections, sections: sections,
@@ -89,14 +93,15 @@ enum AnalyticsGenerator {
private static func getHeader( private static func getHeader(
targets: [TrackerType], targets: [TrackerType],
isStatic: Bool, isStatic: Bool,
visibility: ExtensionVisibility visibility: ExtensionVisibility,
pathSuffix: String
) -> String { ) -> String {
""" """
// Generated by ResgenSwift.\(Analytics.toolName) \(ResgenSwiftVersion) // Generated by ResgenSwift.\(Analytics.toolName) \(ResgenSwiftVersion)
\(Self.getImport(targets: targets)) \(Self.getImport(targets: targets))
\(Self.getAnalyticsProtocol(targets: targets, visibility: visibility)) \(Self.getAnalyticsProtocol(targets: targets, visibility: visibility, pathSuffix: pathSuffix))
\(Self.getTrackerTypeEnum(targets: targets, visibility: visibility)) \(Self.getTrackerTypeEnum(targets: targets, visibility: visibility))
@@ -104,6 +109,7 @@ enum AnalyticsGenerator {
\(visibility) class AnalyticsManager { \(visibility) class AnalyticsManager {
@MainActor
\(visibility) static var shared = AnalyticsManager() \(visibility) static var shared = AnalyticsManager()
private init() {} private init() {}
@@ -143,6 +149,8 @@ enum AnalyticsGenerator {
visibility: ExtensionVisibility visibility: ExtensionVisibility
) -> String { ) -> String {
""" """
private var isDebugMode: Bool = false
private var isEnabled: Bool { private var isEnabled: Bool {
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" { if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
false false
@@ -151,6 +159,8 @@ enum AnalyticsGenerator {
} }
} }
private let logger = Logger(subsystem: "resgen", category: "analytics")
// MARK: - Enable Methods // MARK: - Enable Methods
private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) { private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) {
@@ -186,6 +196,8 @@ enum AnalyticsGenerator {
result.append("import FirebaseAnalytics") result.append("import FirebaseAnalytics")
} }
result.append("import os")
return result.joined(separator: "\n") return result.joined(separator: "\n")
} }
@@ -193,14 +205,40 @@ enum AnalyticsGenerator {
""" """
// MARK: - Private Log Methods // MARK: - Private Log Methods
private func formattedParams(_ params: [String: Any]?) -> String {
guard let params = params, !params.isEmpty else { return "-" }
let formattedParams = params.map { key, value in
" \\(key): \\(value)"
}
.joined(separator: "\\n")
return "\\n" + formattedParams
}
private func logScreen( private func logScreen(
name: String, name: String,
path: String, path: String,
params: [String: Any]? params: [String: Any]?
) { ) {
guard isEnabled else { return } guard isEnabled else {
if isDebugMode {
logger.log("Analytics disabled")
}
return
}
managers.values.forEach { manager in managers.values.forEach { manager in
if isDebugMode {
logger.debug(\"""
🖥️ Screen:
Name: \\(name, privacy: .public)
Path: \\(path, privacy: .public)
Params: \\(self.formattedParams(params), privacy: .public)
\""")
}
manager.logScreen( manager.logScreen(
name: name, name: name,
path: path, path: path,
@@ -215,9 +253,25 @@ enum AnalyticsGenerator {
category: String, category: String,
params: [String: Any]? params: [String: Any]?
) { ) {
guard isEnabled else { return } guard isEnabled else {
if isDebugMode {
logger.log("Analytics disabled")
}
return
}
managers.values.forEach { manager in managers.values.forEach { manager in
if isDebugMode {
logger.debug(\"""
📊 Event:
Name: \\(name, privacy: .public)
Action: \\(action.isEmpty ? "-" : action, privacy: .public)
Category: \\(category.isEmpty ? "-" : category, privacy: .public)
Params: \\(self.formattedParams(params), privacy: .public)
\""")
}
manager.logEvent( manager.logEvent(
name: name, name: name,
action: action, action: action,
@@ -238,11 +292,13 @@ enum AnalyticsGenerator {
let footer = " }" let footer = " }"
if targets.contains(TrackerType.matomo) { if targets.contains(TrackerType.matomo) {
header = "\(visibility) func configure(siteId: String, url: String) {" header = "\(visibility) func configure(siteId: String, url: String, isDebugMode: Bool = false) {"
} else if targets.contains(TrackerType.firebase) { } else if targets.contains(TrackerType.firebase) {
header = "\(visibility) func configure() {" header = "\(visibility) func configure(isDebugMode: Bool = false) {"
} }
content.append(" self.isDebugMode = isDebugMode")
if targets.contains(TrackerType.matomo) { if targets.contains(TrackerType.matomo) {
content.append(""" content.append("""
managers[TrackerType.matomo] = MatomoAnalyticsManager( managers[TrackerType.matomo] = MatomoAnalyticsManager(
@@ -266,7 +322,8 @@ enum AnalyticsGenerator {
private static func getAnalyticsProtocol( private static func getAnalyticsProtocol(
targets: [TrackerType], targets: [TrackerType],
visibility: ExtensionVisibility visibility: ExtensionVisibility,
pathSuffix: String
) -> String { ) -> String {
let proto = """ let proto = """
// MARK: - Protocol // MARK: - Protocol
@@ -293,11 +350,11 @@ enum AnalyticsGenerator {
var result: [String] = [proto] var result: [String] = [proto]
if targets.contains(TrackerType.matomo) { if targets.contains(TrackerType.matomo) {
result.append(MatomoGenerator.service) result.append(MatomoGenerator.service(pathSuffix: pathSuffix))
} }
if targets.contains(TrackerType.firebase) { if targets.contains(TrackerType.firebase) {
result.append(FirebaseGenerator.service) result.append(FirebaseGenerator.service(pathSuffix: pathSuffix))
} }
return result.joined(separator: "\n\n") return result.joined(separator: "\n\n")

View File

@@ -11,10 +11,10 @@ import Foundation
enum FirebaseGenerator { enum FirebaseGenerator {
static var service: String { static func service(pathSuffix: String) -> String {
[ [
Self.header, Self.header,
Self.logScreen, Self.logScreen(pathSuffix: pathSuffix),
Self.logEvent, Self.logEvent,
Self.enable, Self.enable,
Self.footer Self.footer
@@ -35,8 +35,14 @@ enum FirebaseGenerator {
""" """
} }
private static var logScreen: String { private static func logScreen(pathSuffix: String) -> String {
""" let pathSuffixCode: String = if pathSuffix.isEmpty == false {
" + \"/\(pathSuffix)\""
} else {
""
}
return """
func logScreen( func logScreen(
name: String, name: String,
path: String, path: String,
@@ -47,7 +53,7 @@ enum FirebaseGenerator {
] ]
if path.isEmpty == false { if path.isEmpty == false {
parameters["path"] = path + "/iOS" as NSObject parameters["path"] = path\(pathSuffixCode) as NSObject
} }
if let supplementaryParameters = params { if let supplementaryParameters = params {

View File

@@ -11,11 +11,11 @@ import Foundation
enum MatomoGenerator { enum MatomoGenerator {
static var service: String { static func service(pathSuffix: String) -> String {
[ [
Self.header, Self.header,
Self.setup, Self.setup,
Self.logScreen, Self.logScreen(pathSuffix: pathSuffix),
Self.logEvent, Self.logEvent,
Self.enable, Self.enable,
Self.footer Self.footer
@@ -67,8 +67,14 @@ enum MatomoGenerator {
""" """
} }
private static var logScreen: String { private static func logScreen(pathSuffix: String) -> String {
""" let pathSuffixCode: String = if pathSuffix.isEmpty == false {
" + \"/\(pathSuffix)\""
} else {
""
}
return """
func logScreen( func logScreen(
name: String, name: String,
path: String, path: String,
@@ -76,7 +82,7 @@ enum MatomoGenerator {
) { ) {
guard let trackerUrl = tracker.contentBase?.absoluteString else { return } guard let trackerUrl = tracker.contentBase?.absoluteString else { return }
let urlString = URL(string: "\\(trackerUrl)" + "/" + "\\(path)" + "iOS") let urlString = URL(string: "\\(trackerUrl)" + "/" + "\\(path)"\(pathSuffixCode))
tracker.track( tracker.track(
view: [name], view: [name],
url: urlString url: urlString

View File

@@ -169,7 +169,6 @@ class AnalyticsFileParser {
if target.contains(TrackerType.matomo.value) { if target.contains(TrackerType.matomo.value) {
// Path // Path
guard let path = screen.path else { guard let path = screen.path else {
let error = AnalyticsError.missingElement("screen path") let error = AnalyticsError.missingElement("screen path")
print(error.description) print(error.description)
@@ -181,6 +180,10 @@ class AnalyticsFileParser {
definition.path = path definition.path = path
} }
while definition.path.last == "/" {
definition.path = String(definition.path.dropLast())
}
return definition return definition
} }
} }

View File

@@ -13,7 +13,7 @@ struct Fonts: ParsableCommand {
// MARK: - CommandConfiguration // MARK: - CommandConfiguration
static var configuration = CommandConfiguration( static let configuration = CommandConfiguration(
abstract: "A utility to generate an helpful etension to access your custom font from code and also Info.plist UIAppsFont content.", abstract: "A utility to generate an helpful etension to access your custom font from code and also Info.plist UIAppsFont content.",
version: ResgenSwiftVersion version: ResgenSwiftVersion
) )

View File

@@ -13,7 +13,7 @@ struct Generate: ParsableCommand {
// MARK: - CommandConfiguration // MARK: - CommandConfiguration
static var configuration = CommandConfiguration( static let configuration = CommandConfiguration(
abstract: "A utility to generate ressources based on a configuration file", abstract: "A utility to generate ressources based on a configuration file",
version: ResgenSwiftVersion version: ResgenSwiftVersion
) )

View File

@@ -16,12 +16,14 @@ struct GenerateOptions: ParsableArguments {
@Argument(help: "Configuration file.", transform: { $0.replaceTiltWithHomeDirectoryPath() }) @Argument(help: "Configuration file.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
var configurationFile: String var configurationFile: String
@Option(help: "Project directory. It will be added to every relative path (path that does not start with `/`", @Option(
help: "Project directory. It will be added to every relative path (path that does not start with `/`",
transform: { transform: {
if $0.last == "/" { if $0.last == "/" {
return $0 return $0
} }
return $0 + "/" return $0 + "/"
}) }
)
var projectDirectory: String var projectDirectory: String
} }

View File

@@ -61,7 +61,7 @@ struct ConfigurationArchitecture: Codable {
} }
let classDefinition = [ let classDefinition = [
"class \(classname) {", "class \(classname): Sendable {",
children?.map { $0.getProperty(isStatic: generateStaticProperty) }.joined(separator: "\n"), children?.map { $0.getProperty(isStatic: generateStaticProperty) }.joined(separator: "\n"),
"}" "}"
] ]
@@ -89,19 +89,22 @@ struct AnalyticsConfiguration: Codable, CustomDebugStringConvertible {
let outputFile: String let outputFile: String
let visibility: String? let visibility: String?
let staticMembers: Bool? let staticMembers: Bool?
let pathSuffix: String?
internal init( internal init(
inputFile: String, inputFile: String,
target: String, target: String,
outputFile: String, outputFile: String,
visibility: String?, visibility: String?,
staticMembers: Bool? staticMembers: Bool?,
pathSuffix: String?
) { ) {
self.inputFile = inputFile self.inputFile = inputFile
self.target = target self.target = target
self.outputFile = outputFile self.outputFile = outputFile
self.visibility = visibility self.visibility = visibility
self.staticMembers = staticMembers self.staticMembers = staticMembers
self.pathSuffix = pathSuffix
} }
var debugDescription: String { var debugDescription: String {
@@ -112,6 +115,7 @@ struct AnalyticsConfiguration: Codable, CustomDebugStringConvertible {
- Output file: \(outputFile) - Output file: \(outputFile)
- Visiblity: \(visibility ?? "default") - Visiblity: \(visibility ?? "default")
- Static members: \(staticMembers != nil ? "\(String(describing: staticMembers))" : "default") - Static members: \(staticMembers != nil ? "\(String(describing: staticMembers))" : "default")
- Path suffix: \(pathSuffix != nil ? "\(String(describing: pathSuffix))" : "default")
""" """
} }
} }

View File

@@ -32,7 +32,8 @@ extension AnalyticsConfiguration: Runnable {
// Add optional parameters // Add optional parameters
[ [
("--visibility", visibility), ("--visibility", visibility),
("--static-members", staticMembers?.description) ("--static-members", staticMembers?.description),
("--path-suffix", pathSuffix)
].forEach { argumentName, argumentValue in ].forEach { argumentName, argumentValue in
if let argumentValue { if let argumentValue {
args += [ args += [

View File

@@ -38,8 +38,8 @@ extension StringsConfiguration: Runnable {
("--extension-suffix", extensionSuffix), ("--extension-suffix", extensionSuffix),
("--visibility", visibility), ("--visibility", visibility),
("--asset-bundle", assetBundle), ("--asset-bundle", assetBundle),
("--xc-strings", staticMembers?.description), ("--xc-strings", xcStrings?.description),
("--static-members", xcStrings?.description) ("--static-members", staticMembers?.description)
].forEach { argumentName, argumentValue in ].forEach { argumentName, argumentValue in
if let argumentValue { if let argumentValue {
args += [ args += [

View File

@@ -186,8 +186,6 @@ class XcassetsGenerator {
atomically: false, atomically: false,
encoding: .utf8 encoding: .utf8
) )
print("\(parsedImage.name) -> Generated")
} }
// Success info // Success info

View File

@@ -13,7 +13,7 @@ struct Images: ParsableCommand {
// MARK: - CommandConfiguration // MARK: - CommandConfiguration
static var configuration = CommandConfiguration( static let configuration = CommandConfiguration(
abstract: "A utility for generate images and an extension to access them easily.", abstract: "A utility for generate images and an extension to access them easily.",
version: ResgenSwiftVersion version: ResgenSwiftVersion
) )

View File

@@ -133,15 +133,17 @@ enum StringsFileGenerator {
tags inputTags: [String], tags inputTags: [String],
sections: [Section] sections: [Section]
) -> String { ) -> String {
let rootObject = generateRootObject( generateXcStringsFileContentFromRootObject(
rootObject: generateRootObject(
langs: langs, langs: langs,
defaultLang: defaultLang, defaultLang: defaultLang,
tags: inputTags, tags: inputTags,
sections: sections sections: sections
) )
let file = generateXcStringsFileContentFromRootObject(rootObject: rootObject) )
// Remove unwanted \ generated when transforming object to json
return file .replacingOccurrences(of: "\\\\", with: "\\")
.replacingOccurrences(of: "\\\"", with: "\"")
} }
static func generateXcStringsFileContentFromRootObject(rootObject: Root) -> String { static func generateXcStringsFileContentFromRootObject(rootObject: Root) -> String {
@@ -174,21 +176,21 @@ enum StringsFileGenerator {
return // Go to next section return // Go to next section
} }
section.definitions.forEach { definition in // swiftlint:disable:this closure_body_length section
var skipDefinition = false .definitions
.forEach { definition in // swiftlint:disable:this closure_body_length
var isNoTranslation = false var isNoTranslation = false
var localizationTab: [XCStringLocalization] = [] var localizationTab: [XCStringLocalization] = []
if definition.hasOneOrMoreMatchingTags(inputTags: inputTags) == false { guard definition.hasOneOrMoreMatchingTags(inputTags: inputTags) else {
skipDefinition = true return
} }
if definition.tags.contains(Stringium.noTranslationTag) { if definition.tags.contains(Stringium.noTranslationTag) {
isNoTranslation = true isNoTranslation = true
} }
if !skipDefinition {
if isNoTranslation { if isNoTranslation {
// Search for langs in yaml // Search for langs in yaml
for lang in langs { for lang in langs {
@@ -196,7 +198,10 @@ enum StringsFileGenerator {
let localization = XCStringLocalization( let localization = XCStringLocalization(
lang: lang, lang: lang,
content: XCStringLocalizationLangContent( content: XCStringLocalizationLangContent(
stringUnit: DefaultStringUnit(state: "translated", value: value) stringUnit: DefaultStringUnit(
state: "translated",
value: value
)
) )
) )
localizationTab.append(localization) localizationTab.append(localization)
@@ -204,14 +209,17 @@ enum StringsFileGenerator {
} }
} else { } else {
// Search for langs in twine // Search for langs in twine
for (lang, value) in definition.translations where !value.isEmpty { for (lang, value) in definition.translations
where langs.contains(lang) && !value.isEmpty {
let localization = XCStringLocalization( let localization = XCStringLocalization(
lang: lang, lang: lang,
content: XCStringLocalizationLangContent( content: XCStringLocalizationLangContent(
stringUnit: DefaultStringUnit(state: "translated", value: value) stringUnit: DefaultStringUnit(
state: "translated",
value: value
)
) )
) )
localizationTab.append(localization) localizationTab.append(localization)
} }
} }
@@ -230,7 +238,6 @@ enum StringsFileGenerator {
xcStringDefinitionTab.append(xcStringDefinition) xcStringDefinitionTab.append(xcStringDefinition)
} }
} }
}
let xcStringContainer = XCStringDefinitionContainer(strings: xcStringDefinitionTab) let xcStringContainer = XCStringDefinitionContainer(strings: xcStringDefinitionTab)

View File

@@ -13,7 +13,7 @@ struct Stringium: ParsableCommand {
// MARK: - Command Configuration // MARK: - Command Configuration
static var configuration = CommandConfiguration( static let configuration = CommandConfiguration(
abstract: "Generate strings with custom scripts.", abstract: "Generate strings with custom scripts.",
version: ResgenSwiftVersion version: ResgenSwiftVersion
) )

View File

@@ -11,7 +11,7 @@ import ToolCore
struct Strings: ParsableCommand { struct Strings: ParsableCommand {
static var configuration = CommandConfiguration( static let configuration = CommandConfiguration(
abstract: "A utility for generate strings.", abstract: "A utility for generate strings.",
version: ResgenSwiftVersion, version: ResgenSwiftVersion,

View File

@@ -13,7 +13,7 @@ struct Tags: ParsableCommand {
// MARK: - Command Configuration // MARK: - Command Configuration
static var configuration = CommandConfiguration( static let configuration = CommandConfiguration(
abstract: "Generate tags extension file.", abstract: "Generate tags extension file.",
version: ResgenSwiftVersion version: ResgenSwiftVersion
) )

View File

@@ -13,7 +13,7 @@ struct Twine: ParsableCommand {
// MARK: - Command Configuration // MARK: - Command Configuration
static var configuration = CommandConfiguration( static let configuration = CommandConfiguration(
abstract: "Generate strings with twine.", abstract: "Generate strings with twine.",
version: ResgenSwiftVersion version: ResgenSwiftVersion
) )

View File

@@ -11,7 +11,7 @@ import ToolCore
struct ResgenSwift: ParsableCommand { struct ResgenSwift: ParsableCommand {
static var configuration = CommandConfiguration( static let configuration = CommandConfiguration(
abstract: "A utility for generate ressources.", abstract: "A utility for generate ressources.",
version: ResgenSwiftVersion, version: ResgenSwiftVersion,

View File

@@ -179,7 +179,7 @@ final class AnalyticsGeneratorTests: XCTestCase {
) { ) {
guard let trackerUrl = tracker.contentBase?.absoluteString else { return } guard let trackerUrl = tracker.contentBase?.absoluteString else { return }
let urlString = URL(string: "\\(trackerUrl)" + "/" + "\\(path)" + "iOS") let urlString = URL(string: "\\(trackerUrl)" + "/" + "\\(path)" + "/iOS")
tracker.track( tracker.track(
view: [name], view: [name],
url: urlString url: urlString
@@ -234,7 +234,8 @@ final class AnalyticsGeneratorTests: XCTestCase {
sections: [sectionOne, sectionTwo, sectionThree], sections: [sectionOne, sectionTwo, sectionThree],
tags: ["ios", "iosonly"], tags: ["ios", "iosonly"],
isStatic: false, isStatic: false,
visibility: .public visibility: .internal,
pathSuffix: "iOS"
) )
// Expect Analytics // Expect Analytics
@@ -243,351 +244,16 @@ final class AnalyticsGeneratorTests: XCTestCase {
import Foundation import Foundation
import FirebaseAnalytics import FirebaseAnalytics
import os
\(protocolString(visibility: .public))
\(firebaseString())
// MARK: - Traker Type
public enum TrackerType: CaseIterable {
case firebase
}
// MARK: - Manager
public class AnalyticsManager {
public static var shared = AnalyticsManager()
private init() {}
// MARK: - Properties
var managers: [TrackerType: AnalyticsManagerProtocol] = [:]
private var isEnabled: Bool {
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
false
} else {
true
}
}
// MARK: - Enable Methods
private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) {
managers.forEach { (key, value) in
if analytics.contains(where: { type in
type == key
}) {
value.setEnable(enable)
}
}
}
public func enableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
setAnalytics(enable: true, analytics)
}
public func disableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
setAnalytics(enable: false, analytics)
}
public func configure() {
managers[TrackerType.firebase] = FirebaseAnalyticsManager()
}
// MARK: - Private Log Methods
private func logScreen(
name: String,
path: String,
params: [String: Any]?
) {
guard isEnabled else { return }
managers.values.forEach { manager in
manager.logScreen(
name: name,
path: path,
params: params
)
}
}
private func logEvent(
name: String,
action: String,
category: String,
params: [String: Any]?
) {
guard isEnabled else { return }
managers.values.forEach { manager in
manager.logEvent(
name: name,
action: action,
category: category,
params: params
)
}
}
// MARK: - section_one
public func logScreenS1DefOne() {
logScreen(
name: "s1 def one",
path: "",
params: nil
)
}
public func logEventS1DefTwo() {
logEvent(
name: "s1 def two",
action: "",
category: "",
params: nil
)
}
// MARK: - section_two
public func logScreenS2DefOne() {
logScreen(
name: "s2 def one",
path: "",
params: nil
)
}
}
"""
if extensionContent != expect {
print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect))
}
XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest())
}
func testGeneratedExtensionContentMatomo() {
// Given
let sectionOne = AnalyticsCategory(id: "section_one")
sectionOne.definitions = [
getAnalyticsDefinition(id: "s1_def_one", path: "s1_def_one/", name: "s1 def one", type: .screen, tags: ["ios", "iosonly"]),
getAnalyticsDefinition(id: "s1_def_two", action: "test", category: "test", name: "s1 def two", type: .event, tags: ["ios", "iosonly"]),
]
let sectionTwo = AnalyticsCategory(id: "section_two")
sectionTwo.definitions = [
getAnalyticsDefinition(id: "s2_def_one", path: "s2_def_one/", name: "s2 def one", type: .screen, tags: ["ios","iosonly"]),
getAnalyticsDefinition(id: "s2_def_two", action: "test", category: "test", name: "s2 def two", type: .event, tags: ["droid","droidonly"]),
]
let sectionThree = AnalyticsCategory(id: "section_three")
sectionThree.definitions = [
getAnalyticsDefinition(id: "s3_def_one", path: "s3_def_one/", name: "s3 def one", type: .screen, tags: ["droid","droidonly"]),
getAnalyticsDefinition(id: "s3_def_two", action: "test", category: "test", name: "s3 def two", type: .event, tags: ["droid","droidonly"]),
]
// When
let extensionContent = AnalyticsGenerator.getExtensionContent(
targets: [TrackerType.matomo],
sections: [sectionOne, sectionTwo, sectionThree],
tags: ["ios", "iosonly"],
isStatic: false,
visibility: .package
)
// Expect Analytics
let expect = """
// Generated by ResgenSwift.Analytics \(ResgenSwiftVersion)
import Foundation
import MatomoTracker
\(protocolString(visibility: .package))
\(matomoString())
// MARK: - Traker Type
package enum TrackerType: CaseIterable {
case matomo
}
// MARK: - Manager
package class AnalyticsManager {
package static var shared = AnalyticsManager()
private init() {}
// MARK: - Properties
var managers: [TrackerType: AnalyticsManagerProtocol] = [:]
private var isEnabled: Bool {
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
false
} else {
true
}
}
// MARK: - Enable Methods
private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) {
managers.forEach { (key, value) in
if analytics.contains(where: { type in
type == key
}) {
value.setEnable(enable)
}
}
}
package func enableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
setAnalytics(enable: true, analytics)
}
package func disableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
setAnalytics(enable: false, analytics)
}
package func configure(siteId: String, url: String) {
managers[TrackerType.matomo] = MatomoAnalyticsManager(
siteId: siteId,
url: url
)
}
// MARK: - Private Log Methods
private func logScreen(
name: String,
path: String,
params: [String: Any]?
) {
guard isEnabled else { return }
managers.values.forEach { manager in
manager.logScreen(
name: name,
path: path,
params: params
)
}
}
private func logEvent(
name: String,
action: String,
category: String,
params: [String: Any]?
) {
guard isEnabled else { return }
managers.values.forEach { manager in
manager.logEvent(
name: name,
action: action,
category: category,
params: params
)
}
}
// MARK: - section_one
package func logScreenS1DefOne() {
logScreen(
name: "s1 def one",
path: "s1_def_one/",
params: nil
)
}
package func logEventS1DefTwo() {
logEvent(
name: "s1 def two",
action: "test",
category: "test",
params: nil
)
}
// MARK: - section_two
package func logScreenS2DefOne() {
logScreen(
name: "s2 def one",
path: "s2_def_one/",
params: nil
)
}
}
"""
if extensionContent != expect {
print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect))
}
XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest())
}
func testGeneratedExtensionContentMatomoAndFirebase() {
// Given
let sectionOne = AnalyticsCategory(id: "section_one")
sectionOne.definitions = [
getAnalyticsDefinition(id: "s1_def_one", path: "s1_def_one/", name: "s1 def one", type: .screen, tags: ["ios", "iosonly"]),
getAnalyticsDefinition(id: "s1_def_two", action: "test", category: "test", name: "s1 def two", type: .event, tags: ["ios", "iosonly"]),
]
let sectionTwo = AnalyticsCategory(id: "section_two")
sectionTwo.definitions = [
getAnalyticsDefinition(id: "s2_def_one", path: "s2_def_one/", name: "s2 def one", type: .screen, tags: ["ios","iosonly"]),
getAnalyticsDefinition(id: "s2_def_two", action: "test", category: "test", name: "s2 def two", type: .event, tags: ["droid","droidonly"]),
]
let sectionThree = AnalyticsCategory(id: "section_three")
sectionThree.definitions = [
getAnalyticsDefinition(id: "s3_def_one", path: "s3_def_one/", name: "s3 def one", type: .screen, tags: ["droid","droidonly"]),
getAnalyticsDefinition(id: "s3_def_two", action: "test", category: "test", name: "s3 def two", type: .event, tags: ["droid","droidonly"]),
]
// When
let extensionContent = AnalyticsGenerator.getExtensionContent(
targets: [TrackerType.matomo, TrackerType.firebase],
sections: [sectionOne, sectionTwo, sectionThree],
tags: ["ios", "iosonly"],
isStatic: false,
visibility: .internal
)
// Expect Analytics
let expect = """
// Generated by ResgenSwift.Analytics \(ResgenSwiftVersion)
import Foundation
import MatomoTracker
import FirebaseAnalytics
\(protocolString(visibility: .internal)) \(protocolString(visibility: .internal))
\(matomoString())
\(firebaseString()) \(firebaseString())
// MARK: - Traker Type // MARK: - Traker Type
internal enum TrackerType: CaseIterable { internal enum TrackerType: CaseIterable {
case matomo
case firebase case firebase
} }
@@ -595,6 +261,7 @@ final class AnalyticsGeneratorTests: XCTestCase {
internal class AnalyticsManager { internal class AnalyticsManager {
@MainActor
internal static var shared = AnalyticsManager() internal static var shared = AnalyticsManager()
private init() {} private init() {}
@@ -603,6 +270,8 @@ final class AnalyticsGeneratorTests: XCTestCase {
var managers: [TrackerType: AnalyticsManagerProtocol] = [:] var managers: [TrackerType: AnalyticsManagerProtocol] = [:]
private var isDebugMode: Bool = false
private var isEnabled: Bool { private var isEnabled: Bool {
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" { if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
false false
@@ -611,6 +280,8 @@ final class AnalyticsGeneratorTests: XCTestCase {
} }
} }
private let logger = Logger(subsystem: "resgen", category: "analytics")
// MARK: - Enable Methods // MARK: - Enable Methods
private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) { private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) {
@@ -631,24 +302,47 @@ final class AnalyticsGeneratorTests: XCTestCase {
setAnalytics(enable: false, analytics) setAnalytics(enable: false, analytics)
} }
internal func configure(siteId: String, url: String) { internal func configure(isDebugMode: Bool = false) {
managers[TrackerType.matomo] = MatomoAnalyticsManager( self.isDebugMode = isDebugMode
siteId: siteId,
url: url
)
managers[TrackerType.firebase] = FirebaseAnalyticsManager() managers[TrackerType.firebase] = FirebaseAnalyticsManager()
} }
// MARK: - Private Log Methods // MARK: - Private Log Methods
private func formattedParams(_ params: [String: Any]?) -> String {
guard let params = params, !params.isEmpty else { return "-" }
let formattedParams = params.map { key, value in
" \\(key): \\(value)"
}
.joined(separator: "\\n")
return "\\n" + formattedParams
}
private func logScreen( private func logScreen(
name: String, name: String,
path: String, path: String,
params: [String: Any]? params: [String: Any]?
) { ) {
guard isEnabled else { return } guard isEnabled else {
if isDebugMode {
logger.log("Analytics disabled")
}
return
}
managers.values.forEach { manager in managers.values.forEach { manager in
if isDebugMode {
logger.debug(\"""
🖥️ Screen:
Name: \\(name, privacy: .public)
Path: \\(path, privacy: .public)
Params: \\(self.formattedParams(params), privacy: .public)
\""")
}
manager.logScreen( manager.logScreen(
name: name, name: name,
path: path, path: path,
@@ -663,9 +357,25 @@ final class AnalyticsGeneratorTests: XCTestCase {
category: String, category: String,
params: [String: Any]? params: [String: Any]?
) { ) {
guard isEnabled else { return } guard isEnabled else {
if isDebugMode {
logger.log("Analytics disabled")
}
return
}
managers.values.forEach { manager in managers.values.forEach { manager in
if isDebugMode {
logger.debug(\"""
📊 Event:
Name: \\(name, privacy: .public)
Action: \\(action.isEmpty ? "-" : action, privacy: .public)
Category: \\(category.isEmpty ? "-" : category, privacy: .public)
Params: \\(self.formattedParams(params), privacy: .public)
\""")
}
manager.logEvent( manager.logEvent(
name: name, name: name,
action: action, action: action,
@@ -680,7 +390,224 @@ final class AnalyticsGeneratorTests: XCTestCase {
internal func logScreenS1DefOne() { internal func logScreenS1DefOne() {
logScreen( logScreen(
name: "s1 def one", name: "s1 def one",
path: "s1_def_one/", path: "",
params: nil
)
}
internal func logEventS1DefTwo() {
logEvent(
name: "s1 def two",
action: "",
category: "",
params: nil
)
}
// MARK: - section_two
internal func logScreenS2DefOne() {
logScreen(
name: "s2 def one",
path: "",
params: nil
)
}
}
"""
if extensionContent != expect {
print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect))
}
XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest())
}
func testGeneratedExtensionContentMatomo() {
// Given
let sectionOne = AnalyticsCategory(id: "section_one")
sectionOne.definitions = [
getAnalyticsDefinition(id: "s1_def_one", path: "s1_def_one", name: "s1 def one", type: .screen, tags: ["ios", "iosonly"]),
getAnalyticsDefinition(id: "s1_def_two", action: "test", category: "test", name: "s1 def two", type: .event, tags: ["ios", "iosonly"]),
]
let sectionTwo = AnalyticsCategory(id: "section_two")
sectionTwo.definitions = [
getAnalyticsDefinition(id: "s2_def_one", path: "s2_def_one", name: "s2 def one", type: .screen, tags: ["ios","iosonly"]),
getAnalyticsDefinition(id: "s2_def_two", action: "test", category: "test", name: "s2 def two", type: .event, tags: ["droid","droidonly"]),
]
let sectionThree = AnalyticsCategory(id: "section_three")
sectionThree.definitions = [
getAnalyticsDefinition(id: "s3_def_one", path: "s3_def_one", name: "s3 def one", type: .screen, tags: ["droid","droidonly"]),
getAnalyticsDefinition(id: "s3_def_two", action: "test", category: "test", name: "s3 def two", type: .event, tags: ["droid","droidonly"]),
]
// When
let extensionContent = AnalyticsGenerator.getExtensionContent(
targets: [TrackerType.matomo],
sections: [sectionOne, sectionTwo, sectionThree],
tags: ["ios", "iosonly"],
isStatic: false,
visibility: .internal,
pathSuffix: "iOS"
)
// Expect Analytics
let expect = """
// Generated by ResgenSwift.Analytics \(ResgenSwiftVersion)
import Foundation
import MatomoTracker
import os
\(protocolString(visibility: .internal))
\(matomoString())
// MARK: - Traker Type
internal enum TrackerType: CaseIterable {
case matomo
}
// MARK: - Manager
internal class AnalyticsManager {
@MainActor
internal static var shared = AnalyticsManager()
private init() {}
// MARK: - Properties
var managers: [TrackerType: AnalyticsManagerProtocol] = [:]
private var isDebugMode: Bool = false
private var isEnabled: Bool {
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
false
} else {
true
}
}
private let logger = Logger(subsystem: "resgen", category: "analytics")
// MARK: - Enable Methods
private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) {
managers.forEach { (key, value) in
if analytics.contains(where: { type in
type == key
}) {
value.setEnable(enable)
}
}
}
internal func enableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
setAnalytics(enable: true, analytics)
}
internal func disableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
setAnalytics(enable: false, analytics)
}
internal func configure(siteId: String, url: String, isDebugMode: Bool = false) {
self.isDebugMode = isDebugMode
managers[TrackerType.matomo] = MatomoAnalyticsManager(
siteId: siteId,
url: url
)
}
// MARK: - Private Log Methods
private func formattedParams(_ params: [String: Any]?) -> String {
guard let params = params, !params.isEmpty else { return "-" }
let formattedParams = params.map { key, value in
" \\(key): \\(value)"
}
.joined(separator: "\\n")
return "\\n" + formattedParams
}
private func logScreen(
name: String,
path: String,
params: [String: Any]?
) {
guard isEnabled else {
if isDebugMode {
logger.log("Analytics disabled")
}
return
}
managers.values.forEach { manager in
if isDebugMode {
logger.debug(\"""
🖥️ Screen:
Name: \\(name, privacy: .public)
Path: \\(path, privacy: .public)
Params: \\(self.formattedParams(params), privacy: .public)
\""")
}
manager.logScreen(
name: name,
path: path,
params: params
)
}
}
private func logEvent(
name: String,
action: String,
category: String,
params: [String: Any]?
) {
guard isEnabled else {
if isDebugMode {
logger.log("Analytics disabled")
}
return
}
managers.values.forEach { manager in
if isDebugMode {
logger.debug(\"""
📊 Event:
Name: \\(name, privacy: .public)
Action: \\(action.isEmpty ? "-" : action, privacy: .public)
Category: \\(category.isEmpty ? "-" : category, privacy: .public)
Params: \\(self.formattedParams(params), privacy: .public)
\""")
}
manager.logEvent(
name: name,
action: action,
category: category,
params: params
)
}
}
// MARK: - section_one
internal func logScreenS1DefOne() {
logScreen(
name: "s1 def one",
path: "s1_def_one",
params: nil params: nil
) )
} }
@@ -699,7 +626,230 @@ final class AnalyticsGeneratorTests: XCTestCase {
internal func logScreenS2DefOne() { internal func logScreenS2DefOne() {
logScreen( logScreen(
name: "s2 def one", name: "s2 def one",
path: "s2_def_one/", path: "s2_def_one",
params: nil
)
}
}
"""
if extensionContent != expect {
print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect))
}
XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest())
}
func testGeneratedExtensionContentMatomoAndFirebase() {
// Given
let sectionOne = AnalyticsCategory(id: "section_one")
sectionOne.definitions = [
getAnalyticsDefinition(id: "s1_def_one", path: "s1_def_one", name: "s1 def one", type: .screen, tags: ["ios", "iosonly"]),
getAnalyticsDefinition(id: "s1_def_two", action: "test", category: "test", name: "s1 def two", type: .event, tags: ["ios", "iosonly"]),
]
let sectionTwo = AnalyticsCategory(id: "section_two")
sectionTwo.definitions = [
getAnalyticsDefinition(id: "s2_def_one", path: "s2_def_one", name: "s2 def one", type: .screen, tags: ["ios","iosonly"]),
getAnalyticsDefinition(id: "s2_def_two", action: "test", category: "test", name: "s2 def two", type: .event, tags: ["droid","droidonly"]),
]
let sectionThree = AnalyticsCategory(id: "section_three")
sectionThree.definitions = [
getAnalyticsDefinition(id: "s3_def_one", path: "s3_def_one", name: "s3 def one", type: .screen, tags: ["droid","droidonly"]),
getAnalyticsDefinition(id: "s3_def_two", action: "test", category: "test", name: "s3 def two", type: .event, tags: ["droid","droidonly"]),
]
// When
let extensionContent = AnalyticsGenerator.getExtensionContent(
targets: [TrackerType.matomo, TrackerType.firebase],
sections: [sectionOne, sectionTwo, sectionThree],
tags: ["ios", "iosonly"],
isStatic: false,
visibility: .internal,
pathSuffix: "iOS"
)
// Expect Analytics
let expect = """
// Generated by ResgenSwift.Analytics \(ResgenSwiftVersion)
import Foundation
import MatomoTracker
import FirebaseAnalytics
import os
\(protocolString(visibility: .internal))
\(matomoString())
\(firebaseString())
// MARK: - Traker Type
internal enum TrackerType: CaseIterable {
case matomo
case firebase
}
// MARK: - Manager
internal class AnalyticsManager {
@MainActor
internal static var shared = AnalyticsManager()
private init() {}
// MARK: - Properties
var managers: [TrackerType: AnalyticsManagerProtocol] = [:]
private var isDebugMode: Bool = false
private var isEnabled: Bool {
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
false
} else {
true
}
}
private let logger = Logger(subsystem: "resgen", category: "analytics")
// MARK: - Enable Methods
private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) {
managers.forEach { (key, value) in
if analytics.contains(where: { type in
type == key
}) {
value.setEnable(enable)
}
}
}
internal func enableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
setAnalytics(enable: true, analytics)
}
internal func disableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) {
setAnalytics(enable: false, analytics)
}
internal func configure(siteId: String, url: String, isDebugMode: Bool = false) {
self.isDebugMode = isDebugMode
managers[TrackerType.matomo] = MatomoAnalyticsManager(
siteId: siteId,
url: url
)
managers[TrackerType.firebase] = FirebaseAnalyticsManager()
}
// MARK: - Private Log Methods
private func formattedParams(_ params: [String: Any]?) -> String {
guard let params = params, !params.isEmpty else { return "-" }
let formattedParams = params.map { key, value in
" \\(key): \\(value)"
}
.joined(separator: "\\n")
return "\\n" + formattedParams
}
private func logScreen(
name: String,
path: String,
params: [String: Any]?
) {
guard isEnabled else {
if isDebugMode {
logger.log("Analytics disabled")
}
return
}
managers.values.forEach { manager in
if isDebugMode {
logger.debug(\"""
🖥️ Screen:
Name: \\(name, privacy: .public)
Path: \\(path, privacy: .public)
Params: \\(self.formattedParams(params), privacy: .public)
\""")
}
manager.logScreen(
name: name,
path: path,
params: params
)
}
}
private func logEvent(
name: String,
action: String,
category: String,
params: [String: Any]?
) {
guard isEnabled else {
if isDebugMode {
logger.log("Analytics disabled")
}
return
}
managers.values.forEach { manager in
if isDebugMode {
logger.debug(\"""
📊 Event:
Name: \\(name, privacy: .public)
Action: \\(action.isEmpty ? "-" : action, privacy: .public)
Category: \\(category.isEmpty ? "-" : category, privacy: .public)
Params: \\(self.formattedParams(params), privacy: .public)
\""")
}
manager.logEvent(
name: name,
action: action,
category: category,
params: params
)
}
}
// MARK: - section_one
internal func logScreenS1DefOne() {
logScreen(
name: "s1 def one",
path: "s1_def_one",
params: nil
)
}
internal func logEventS1DefTwo() {
logEvent(
name: "s1 def two",
action: "test",
category: "test",
params: nil
)
}
// MARK: - section_two
internal func logScreenS2DefOne() {
logScreen(
name: "s2 def one",
path: "s2_def_one",
params: nil params: nil
) )
} }

View File

@@ -20,7 +20,8 @@ final class AnalyticsConfigurationTests: XCTestCase {
target: "matomo firebase", target: "matomo firebase",
outputFile: "Analytics/Generated/AnalyticsManager.swift", outputFile: "Analytics/Generated/AnalyticsManager.swift",
visibility: nil, visibility: nil,
staticMembers: nil staticMembers: nil,
pathSuffix: nil
) )
// When // When
@@ -48,7 +49,8 @@ final class AnalyticsConfigurationTests: XCTestCase {
target: "matomo firebase", target: "matomo firebase",
outputFile: "Analytics/Generated/AnalyticsManager.swift", outputFile: "Analytics/Generated/AnalyticsManager.swift",
visibility: "public", visibility: "public",
staticMembers: false staticMembers: false,
pathSuffix: "mySuffix"
) )
// When // When
@@ -68,7 +70,9 @@ final class AnalyticsConfigurationTests: XCTestCase {
"--visibility", "--visibility",
"public", "public",
"--static-members", "--static-members",
"false" "false",
"--path-suffix",
"mySuffix"
] ]
XCTAssertEqual(arguments, expectedArguments) XCTAssertEqual(arguments, expectedArguments)