YamlMerger/Sources/YAMLMerger/YAMLMerger.swift
2025-10-15 16:52:10 +02:00

73 lines
2.7 KiB
Swift

import Foundation
public struct YAMLMerger {
public let rootDirectory: URL
public let outputFileName: String
public init(rootDirectory: URL, outputFileName: String) {
self.rootDirectory = rootDirectory
self.outputFileName = outputFileName
}
private func sortedYAMLFiles(in folder: URL) -> [URL] {
let fileManager = FileManager.default
guard let contents = try? fileManager.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil) else {
return []
}
return contents
.filter { $0.pathExtension == "yaml" || $0.pathExtension == "yml" }
.sorted { $0.lastPathComponent.lowercased() < $1.lastPathComponent.lowercased() }
}
private func sortedSubfolders(in folder: URL) -> [URL] {
let fileManager = FileManager.default
guard let contents = try? fileManager.contentsOfDirectory(at: folder, includingPropertiesForKeys: [.isDirectoryKey]) else {
return []
}
return contents
.filter {
var isDirectory: ObjCBool = false
return fileManager.fileExists(atPath: $0.path, isDirectory: &isDirectory) && isDirectory.boolValue
}
.sorted { $0.lastPathComponent.lowercased() < $1.lastPathComponent.lowercased() }
}
private func cleanedContent(_ text: String) -> String {
let pattern = "(\\n\\s*){2,}"
let regex: NSRegularExpression
do {
regex = try NSRegularExpression(pattern: pattern, options: [])
} catch {
// If the regex pattern fails to compile, return the original text unchanged.
return text
}
let range = NSRange(location: 0, length: text.utf16.count)
return regex.stringByReplacingMatches(in: text, options: [], range: range, withTemplate: "\n\n")
}
public func merge() {
let outputFile = rootDirectory.appendingPathComponent(outputFileName)
var output = ""
let folderURLs = sortedSubfolders(in: rootDirectory)
for folderURL in folderURLs {
let yamlFiles = sortedYAMLFiles(in: folderURL)
var isFirstFile = true
for fileURL in yamlFiles {
guard let content = try? String(contentsOf: fileURL, encoding: .utf8) else { continue }
if !isFirstFile {
output += "\n" // only between files
}
output += cleanedContent(content)
isFirstFile = false
}
}
try? output.write(to: outputFile, atomically: true, encoding: .utf8)
print("✅ Combined YAML written to \(outputFile.path)")
}
}