diff --git a/Sources/owowgenerate-ios/Configuration/Configuration.swift b/Sources/owowgenerate-ios/Configuration/Configuration.swift index 8ec509e..96a5519 100644 --- a/Sources/owowgenerate-ios/Configuration/Configuration.swift +++ b/Sources/owowgenerate-ios/Configuration/Configuration.swift @@ -22,7 +22,7 @@ struct Configuration: Decodable { var outputFiles: Set { return Set(tasks.compactMap { task -> [String]? in switch task.type { - case .generateSwiftUIMapping, .generateNSLocalizedStringMapping, .generateSwiftUIMappingPublic, .generateNSLocalizedStringMappingPublic: + case .generateSwiftUIMapping, .generateNSLocalizedStringMapping: return task.output.map { [$0] } case .rewriteTranslationFiles: return Array(stringsFiles.suffix(from: 1)) @@ -45,9 +45,7 @@ struct Configuration: Decodable { struct Task: Decodable { enum TaskType: String, Codable { case generateSwiftUIMapping - case generateSwiftUIMappingPublic case generateNSLocalizedStringMapping - case generateNSLocalizedStringMappingPublic case rewriteTranslationFiles case generateInputXcFileList case generateOutputXcFileList @@ -58,6 +56,9 @@ struct Task: Decodable { /// The output file of the task. var output: String? + + /// Options for the task. + var options: TaskOptions? } enum CaseStyle: String, Codable { @@ -73,3 +74,11 @@ enum CaseStyle: String, Codable { } } } + +struct TaskOptions: Codable { + /// The access level modifier (`internal`, `public`, etc) to use for generated code in the task. + var accessLevel: String? = nil + + /// The `Bundle` to use in generated code. For example: `.module`, `Bundle(for: SomeClass.self)`, `Bundle(identifier: ...)` + var bundle: String? = nil +} diff --git a/Sources/owowgenerate-ios/Writers/NSLocalizedStringWriter.swift b/Sources/owowgenerate-ios/Writers/NSLocalizedStringWriter.swift index f214a74..ea7cca4 100644 --- a/Sources/owowgenerate-ios/Writers/NSLocalizedStringWriter.swift +++ b/Sources/owowgenerate-ios/Writers/NSLocalizedStringWriter.swift @@ -1,36 +1,28 @@ -fileprivate var isConstructingForLibrary = false - -func makeLocalizedStringCode(strings: StringsCollection, isForLibrary: Bool) -> String { - if isForLibrary { - isConstructingForLibrary = isForLibrary - } - +func makeLocalizedStringCode(strings: StringsCollection, accessLevel: String?, bundle: String?) -> String { var writer = SwiftCodeWriter() writer.addLine("import Foundation") writer.addLine() - let extensionText = (isConstructingForLibrary ? "public " : "") + "enum Strings" + let aclPrefix = accessLevel.map { $0 + " " } ?? "" - writer.inBlock(extensionText) { writer in - writeStrings(strings: strings, writer: &writer) + writer.inBlock(aclPrefix + "enum Strings") { writer in + writeStrings(strings: strings, writer: &writer, aclPrefix: aclPrefix, bundle: bundle) } return writer.output } -private func writeStrings(strings: StringsCollection, writer: inout SwiftCodeWriter) { +private func writeStrings(strings: StringsCollection, writer: inout SwiftCodeWriter, aclPrefix: String, bundle: String?) { for (name, collection) in strings.subCollections.sorted(by: { $0.key < $1.key }) { writer.addLine() let variableName = name.camelCase(from: config.caseStyle, upper: false).swiftIdentifier let typeName = (name.camelCase(from: config.caseStyle, upper: true)).swiftIdentifier - let line = (isConstructingForLibrary ? "public " : "") + "static var \(variableName): \(typeName).Type { \(typeName).self }" - let structBlock = (isConstructingForLibrary ? "public " : "") + "struct \(typeName)" + writer.addLine(aclPrefix + "static var \(variableName): \(typeName).Type { \(typeName).self }") - writer.addLine(line) - writer.inBlock(structBlock) { writer in - writeStrings(strings: collection, writer: &writer) + writer.inBlock(aclPrefix + "struct \(typeName)") { writer in + writeStrings(strings: collection, writer: &writer, aclPrefix: aclPrefix, bundle: bundle) } } @@ -38,11 +30,11 @@ private func writeStrings(strings: StringsCollection, writer: inout SwiftCodeWri writer.addDocComment(key.comment) let memberName = (key.key.split(separator: ".").last ?? "").camelCase(from: config.caseStyle, upper: false) - let getLocalizedString = "NSLocalizedString(\"\(key.key)\", comment: \(SwiftCodeWriter.makeStringLiteral(key.comment)))" - + let bundleArgument = bundle.map { ", bundle: " + $0 } ?? "" + let getLocalizedString = "NSLocalizedString(\"\(key.key)\"\(bundleArgument), comment: \(SwiftCodeWriter.makeStringLiteral(key.comment)))" + if key.placeholders.isEmpty { - let line = (isConstructingForLibrary ? "public " : "") + "static var \(memberName): String { \(getLocalizedString) }" - writer.addLine(line) + writer.addLine(aclPrefix + "static var \(memberName): String { \(getLocalizedString) }") } else { let parameters = key.placeholders.enumerated().map { index, type in "_ placeholder\(index): \(type.rawValue)" @@ -50,9 +42,7 @@ private func writeStrings(strings: StringsCollection, writer: inout SwiftCodeWri let parameterUsage = key.placeholders.indices.map { "placeholder\($0)" }.joined(separator: ", ") - let functionBlock = (isConstructingForLibrary ? "public " : "") + "static func \(memberName)(\(parameters)) -> String" - - writer.inBlock(functionBlock) { writer in + writer.inBlock(aclPrefix + "static func \(memberName)(\(parameters)) -> String") { writer in writer.addLine("let format = \(getLocalizedString)") writer.addLine("return String(format: format, \(parameterUsage))") } diff --git a/Sources/owowgenerate-ios/Writers/SwiftUICodeWriter.swift b/Sources/owowgenerate-ios/Writers/SwiftUICodeWriter.swift index b2d16fd..8e86cd8 100644 --- a/Sources/owowgenerate-ios/Writers/SwiftUICodeWriter.swift +++ b/Sources/owowgenerate-ios/Writers/SwiftUICodeWriter.swift @@ -1,46 +1,28 @@ -fileprivate var shouldBePublic = false -fileprivate var isConstructingForLibrary = false - -func makeSwiftUICode(strings: StringsCollection, isForLibrary: Bool) -> String { - if isForLibrary { - isConstructingForLibrary = isForLibrary - shouldBePublic = false - } - +func makeSwiftUICode(strings: StringsCollection, accessLevel: String?, bundle: String?) -> String { var writer = SwiftCodeWriter() writer.addLine("import SwiftUI") writer.addLine() - let extensionText = (isConstructingForLibrary ? "public " : "") + "extension SwiftUI.Text" + let aclPrefix = accessLevel.map { $0 + " " } ?? "" - writer.inBlock(extensionText) { writer in - writeStrings(strings: strings, writer: &writer) + writer.inBlock("extension SwiftUI.Text") { writer in + writeStrings(strings: strings, writer: &writer, aclPrefix: aclPrefix, bundle: bundle) } return writer.output } -fileprivate func writeStrings(strings: StringsCollection, writer: inout SwiftCodeWriter) { +fileprivate func writeStrings(strings: StringsCollection, writer: inout SwiftCodeWriter, aclPrefix: String, bundle: String?) { for (name, collection) in strings.subCollections.sorted(by: { $0.key < $1.key }) { writer.addLine() let variableName = name.camelCase(from: config.caseStyle, upper: false).swiftIdentifier let typeName = (name.camelCase(from: config.caseStyle, upper: true) + "StringsNamespace").swiftIdentifier - if shouldBePublic && isConstructingForLibrary { - writer.addLine("public static var \(variableName): \(typeName).Type { \(typeName).self }") - - writer.inBlock("public struct \(typeName)") { writer in - writeStrings(strings: collection, writer: &writer) - } - } else { - shouldBePublic = true - writer.addLine("static var \(variableName): \(typeName).Type { \(typeName).self }") - - writer.inBlock("struct \(typeName)") { writer in - writeStrings(strings: collection, writer: &writer) - } - shouldBePublic = false + writer.addLine(aclPrefix + "static var \(variableName): \(typeName).Type { \(typeName).self }") + + writer.inBlock(aclPrefix + "struct \(typeName)") { writer in + writeStrings(strings: collection, writer: &writer, aclPrefix: aclPrefix, bundle: bundle) } } @@ -48,18 +30,18 @@ fileprivate func writeStrings(strings: StringsCollection, writer: inout SwiftCod let memberName = (key.key.split(separator: ".").last ?? "").camelCase(from: config.caseStyle, upper: false) if key.placeholders.isEmpty { - let additionalArguments: String + var additionalArguments = "" + + if let bundle = bundle { + additionalArguments += ", bundle: \(bundle)" + } + if !key.comment.isEmpty { - additionalArguments = ", comment: \(SwiftCodeWriter.makeStringLiteral(key.comment))" - } else { - additionalArguments = "" + additionalArguments += ", comment: \(SwiftCodeWriter.makeStringLiteral(key.comment))" } writer.addDocComment(key.comment) - - let line = (isConstructingForLibrary ? "public " : "") + "static var \(memberName): Text { Text(\"\(key.key)\"\(additionalArguments)) }" - - writer.addLine(line) + writer.addLine(aclPrefix + "static var \(memberName): Text { Text(\"\(key.key)\"\(additionalArguments)) }") } else { let parameters = key.placeholders.enumerated().map { index, type in "_ placeholder\(index): \(type.rawValue)" @@ -68,10 +50,7 @@ fileprivate func writeStrings(strings: StringsCollection, writer: inout SwiftCod let parameterUsage = key.placeholders.indices.map { "placeholder\($0)" }.joined(separator: ", ") writer.addDocComment(key.comment) - - let functionBlock = (isConstructingForLibrary ? "public " :"") + "static func \(memberName)(\(parameters)) -> Text" - - writer.inBlock(functionBlock) { writer in + writer.inBlock(aclPrefix + "static func \(memberName)(\(parameters)) -> Text") { writer in writer.addLine("let format = NSLocalizedString(\"\(key.key)\", comment: \(SwiftCodeWriter.makeStringLiteral(key.comment)))") writer.addLine("let string = String(format: format, \(parameterUsage))") writer.addLine("return Text(verbatim: string)") diff --git a/Sources/owowgenerate-ios/main.swift b/Sources/owowgenerate-ios/main.swift index 8899bc6..5742766 100644 --- a/Sources/owowgenerate-ios/main.swift +++ b/Sources/owowgenerate-ios/main.swift @@ -21,13 +21,17 @@ for task in config.tasks { switch task.type { case .generateSwiftUIMapping: - output = makeSwiftUICode(strings: strings, isForLibrary: false) - case .generateSwiftUIMappingPublic: - output = makeSwiftUICode(strings: strings, isForLibrary: true) + output = makeSwiftUICode( + strings: strings, + accessLevel: task.options?.accessLevel, + bundle: task.options?.bundle + ) case .generateNSLocalizedStringMapping: - output = makeLocalizedStringCode(strings: strings, isForLibrary: false) - case .generateNSLocalizedStringMappingPublic: - output = makeLocalizedStringCode(strings: strings, isForLibrary: true) + output = makeLocalizedStringCode( + strings: strings, + accessLevel: task.options?.accessLevel, + bundle: task.options?.bundle + ) case .rewriteTranslationFiles: try! rewriteTranslationFiles(paths: config.stringsFiles) continue