diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20fdd34..6b64884 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,13 +4,20 @@ on: push: branches: - '**' + tags: + - "*.*.*" workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build-swiftpm: name: Build SwiftPM uses: oversizedev/GithubWorkflows/.github/workflows/build-swiftpm.yml@main + if: github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/') strategy: matrix: destination: @@ -35,3 +42,9 @@ jobs: if: github.ref == 'refs/heads/main' uses: oversizedev/GithubWorkflows/.github/workflows/bump.yml@main secrets: inherit + + release: + name: Create Release + if: github.ref != 'refs/heads/main' && startsWith(github.ref, 'refs/tags/') + uses: oversizedev/GithubWorkflows/.github/workflows/release.yml@main + secrets: inherit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 0242e2a..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Release - -on: - push: - tags: - - "*.*.*" - -jobs: - build: - name: Create release - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Release - uses: softprops/action-gh-release@v1 diff --git a/.swiftformat b/.swiftformat index 2f6ed6f..b12b883 100644 --- a/.swiftformat +++ b/.swiftformat @@ -1,2 +1,3 @@ ---swiftversion 5.7 ---disable preferKeyPath \ No newline at end of file +--swiftversion 6.0 +--disable preferKeyPath +--ifdef no-indent \ No newline at end of file diff --git a/Sources/OversizeCore/Extensions/Color/Color+Extension.swift b/Sources/OversizeCore/Extensions/Color/Color+Extension.swift index cb08b81..bc8a1bc 100644 --- a/Sources/OversizeCore/Extensions/Color/Color+Extension.swift +++ b/Sources/OversizeCore/Extensions/Color/Color+Extension.swift @@ -6,41 +6,41 @@ import SwiftUI #if os(iOS) - // swiftlint:disable large_tuple - public extension Color { - var components: (red: CGFloat, green: CGFloat, blue: CGFloat, opacity: CGFloat) { - #if canImport(UIKit) - typealias NativeColor = UIColor - #elseif canImport(AppKit) - typealias NativeColor = NSColor - #endif - - var r: CGFloat = 0 - var g: CGFloat = 0 - var b: CGFloat = 0 - var o: CGFloat = 0 - - guard NativeColor(self).getRed(&r, green: &g, blue: &b, alpha: &o) else { - return (0, 0, 0, 0) - } - return (r, g, b, o) +// swiftlint:disable large_tuple +public extension Color { + var components: (red: CGFloat, green: CGFloat, blue: CGFloat, opacity: CGFloat) { + #if canImport(UIKit) + typealias NativeColor = UIColor + #elseif canImport(AppKit) + typealias NativeColor = NSColor + #endif + + var r: CGFloat = 0 + var g: CGFloat = 0 + var b: CGFloat = 0 + var o: CGFloat = 0 + + guard NativeColor(self).getRed(&r, green: &g, blue: &b, alpha: &o) else { + return (0, 0, 0, 0) } + return (r, g, b, o) + } - func lighter(by percentage: CGFloat = 30.0) -> Color { - adjust(by: abs(percentage)) - } + func lighter(by percentage: CGFloat = 30.0) -> Color { + adjust(by: abs(percentage)) + } - func darker(by percentage: CGFloat = 30.0) -> Color { - adjust(by: -1 * abs(percentage)) - } + func darker(by percentage: CGFloat = 30.0) -> Color { + adjust(by: -1 * abs(percentage)) + } - func adjust(by percentage: CGFloat = 30.0) -> Color { - Color(red: min(Double(components.red + percentage / 100), 1.0), - green: min(Double(components.green + percentage / 100), 1.0), - blue: min(Double(components.blue + percentage / 100), 1.0), - opacity: Double(components.opacity)) - } + func adjust(by percentage: CGFloat = 30.0) -> Color { + Color(red: min(Double(components.red + percentage / 100), 1.0), + green: min(Double(components.green + percentage / 100), 1.0), + blue: min(Double(components.blue + percentage / 100), 1.0), + opacity: Double(components.opacity)) } +} #endif public extension Color { diff --git a/Sources/OversizeCore/Extensions/Color/Color+Hex.swift b/Sources/OversizeCore/Extensions/Color/Color+Hex.swift index 8ebb19f..7bcb7ff 100644 --- a/Sources/OversizeCore/Extensions/Color/Color+Hex.swift +++ b/Sources/OversizeCore/Extensions/Color/Color+Hex.swift @@ -5,9 +5,9 @@ import SwiftUI #if canImport(UIKit) - import UIKit +import UIKit #elseif canImport(AppKit) - import AppKit +import AppKit #endif public typealias ColorComponentsRGBA = (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) @@ -76,9 +76,9 @@ public extension Color { var rgba: ColorComponentsRGBA { #if canImport(AppKit) - let color = NSColor(self).usingColorSpace(.displayP3)! + let color = NSColor(self).usingColorSpace(.displayP3)! #elseif canImport(UIKit) - let color: UIColor = .init(self) + let color: UIColor = .init(self) #endif var t = (CGFloat(), CGFloat(), CGFloat(), CGFloat()) diff --git a/Sources/OversizeCore/Extensions/Image/Image+Data.swift b/Sources/OversizeCore/Extensions/Image/Image+Data.swift index 040ea54..26e3b22 100644 --- a/Sources/OversizeCore/Extensions/Image/Image+Data.swift +++ b/Sources/OversizeCore/Extensions/Image/Image+Data.swift @@ -4,28 +4,28 @@ // #if canImport(UIKit) - import UIKit +import UIKit #elseif canImport(AppKit) - import AppKit +import AppKit #endif import SwiftUI public extension Image { init?(data: Data) { #if canImport(UIKit) - if let uiImage = UIImage(data: data) { - self.init(uiImage: uiImage) - } else { - return nil - } + if let uiImage = UIImage(data: data) { + self.init(uiImage: uiImage) + } else { + return nil + } #elseif canImport(AppKit) - if let nsImage = NSImage(data: data) { - self.init(nsImage: nsImage) - } else { - return nil - } - #else + if let nsImage = NSImage(data: data) { + self.init(nsImage: nsImage) + } else { return nil + } + #else + return nil #endif } } diff --git a/Sources/OversizeCore/Extensions/Image/NSImage+Extension.swift b/Sources/OversizeCore/Extensions/Image/NSImage+Extension.swift index 0715a45..4d341f5 100644 --- a/Sources/OversizeCore/Extensions/Image/NSImage+Extension.swift +++ b/Sources/OversizeCore/Extensions/Image/NSImage+Extension.swift @@ -4,63 +4,63 @@ // #if canImport(AppKit) - import AppKit +import AppKit #endif #if canImport(AppKit) - public extension NSImage { - func pngData() -> Data? { - guard let cgImage = cgImage(forProposedRect: nil, context: nil, hints: nil) else { - return nil - } - - let bitmapRepresentation = NSBitmapImageRep(cgImage: cgImage) - return bitmapRepresentation.representation(using: .png, properties: [:]) +public extension NSImage { + func pngData() -> Data? { + guard let cgImage = cgImage(forProposedRect: nil, context: nil, hints: nil) else { + return nil } - } - public extension NSImage { - func jpegData(compressionQuality _: CGFloat) -> Data? { - guard let cgImage = cgImage(forProposedRect: nil, context: nil, hints: nil) else { - return nil - } + let bitmapRepresentation = NSBitmapImageRep(cgImage: cgImage) + return bitmapRepresentation.representation(using: .png, properties: [:]) + } +} - let bitmapRepresentation = NSBitmapImageRep(cgImage: cgImage) - return bitmapRepresentation.representation(using: .jpeg, properties: [:]) +public extension NSImage { + func jpegData(compressionQuality _: CGFloat) -> Data? { + guard let cgImage = cgImage(forProposedRect: nil, context: nil, hints: nil) else { + return nil } - func jpegData() -> Data? { - guard let cgImage = cgImage(forProposedRect: nil, context: nil, hints: nil) else { - return nil - } + let bitmapRepresentation = NSBitmapImageRep(cgImage: cgImage) + return bitmapRepresentation.representation(using: .jpeg, properties: [:]) + } - let bitmapRepresentation = NSBitmapImageRep(cgImage: cgImage) - return bitmapRepresentation.representation(using: .jpeg, properties: [:]) + func jpegData() -> Data? { + guard let cgImage = cgImage(forProposedRect: nil, context: nil, hints: nil) else { + return nil } + + let bitmapRepresentation = NSBitmapImageRep(cgImage: cgImage) + return bitmapRepresentation.representation(using: .jpeg, properties: [:]) } +} - public extension NSImage { - var cgImage: CGImage? { - cgImage(forProposedRect: nil, context: nil, hints: nil) - } +public extension NSImage { + var cgImage: CGImage? { + cgImage(forProposedRect: nil, context: nil, hints: nil) } +} - public extension NSImage { - var averageColor: NSColor? { - guard let cgImage = cgImage(forProposedRect: nil, context: nil, hints: nil) else { return nil } - let inputImage = CIImage(cgImage: cgImage) +public extension NSImage { + var averageColor: NSColor? { + guard let cgImage = cgImage(forProposedRect: nil, context: nil, hints: nil) else { return nil } + let inputImage = CIImage(cgImage: cgImage) - let extentVector = CIVector(x: inputImage.extent.origin.x, y: inputImage.extent.origin.y, z: inputImage.extent.size.width, w: inputImage.extent.size.height) + let extentVector = CIVector(x: inputImage.extent.origin.x, y: inputImage.extent.origin.y, z: inputImage.extent.size.width, w: inputImage.extent.size.height) - guard let filter = CIFilter(name: "CIAreaAverage", parameters: [kCIInputImageKey: inputImage, kCIInputExtentKey: extentVector]) else { return nil } - guard let outputImage = filter.outputImage else { return nil } + guard let filter = CIFilter(name: "CIAreaAverage", parameters: [kCIInputImageKey: inputImage, kCIInputExtentKey: extentVector]) else { return nil } + guard let outputImage = filter.outputImage else { return nil } - var bitmap = [UInt8](repeating: 0, count: 4) - let context = CIContext(options: [.workingColorSpace: kCFNull!]) - context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil) + var bitmap = [UInt8](repeating: 0, count: 4) + let context = CIContext(options: [.workingColorSpace: kCFNull!]) + context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil) - return NSColor(red: CGFloat(bitmap[0]) / 255, green: CGFloat(bitmap[1]) / 255, blue: CGFloat(bitmap[2]) / 255, alpha: CGFloat(bitmap[3]) / 255) - } + return NSColor(red: CGFloat(bitmap[0]) / 255, green: CGFloat(bitmap[1]) / 255, blue: CGFloat(bitmap[2]) / 255, alpha: CGFloat(bitmap[3]) / 255) } +} #endif diff --git a/Sources/OversizeCore/Extensions/Image/UIImage+Extension.swift b/Sources/OversizeCore/Extensions/Image/UIImage+Extension.swift index 6ae6343..c3f1cd6 100644 --- a/Sources/OversizeCore/Extensions/Image/UIImage+Extension.swift +++ b/Sources/OversizeCore/Extensions/Image/UIImage+Extension.swift @@ -4,23 +4,23 @@ // #if canImport(UIKit) - import UIKit +import UIKit #endif #if canImport(UIKit) && !os(watchOS) - public extension UIImage { - var averageColor: UIColor? { - guard let inputImage = CIImage(image: self) else { return nil } - let extentVector = CIVector(x: inputImage.extent.origin.x, y: inputImage.extent.origin.y, z: inputImage.extent.size.width, w: inputImage.extent.size.height) +public extension UIImage { + var averageColor: UIColor? { + guard let inputImage = CIImage(image: self) else { return nil } + let extentVector = CIVector(x: inputImage.extent.origin.x, y: inputImage.extent.origin.y, z: inputImage.extent.size.width, w: inputImage.extent.size.height) - guard let filter = CIFilter(name: "CIAreaAverage", parameters: [kCIInputImageKey: inputImage, kCIInputExtentKey: extentVector]) else { return nil } - guard let outputImage = filter.outputImage else { return nil } + guard let filter = CIFilter(name: "CIAreaAverage", parameters: [kCIInputImageKey: inputImage, kCIInputExtentKey: extentVector]) else { return nil } + guard let outputImage = filter.outputImage else { return nil } - var bitmap = [UInt8](repeating: 0, count: 4) - let context = CIContext(options: [.workingColorSpace: kCFNull!]) - context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil) + var bitmap = [UInt8](repeating: 0, count: 4) + let context = CIContext(options: [.workingColorSpace: kCFNull!]) + context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil) - return UIColor(red: CGFloat(bitmap[0]) / 255, green: CGFloat(bitmap[1]) / 255, blue: CGFloat(bitmap[2]) / 255, alpha: CGFloat(bitmap[3]) / 255) - } + return UIColor(red: CGFloat(bitmap[0]) / 255, green: CGFloat(bitmap[1]) / 255, blue: CGFloat(bitmap[2]) / 255, alpha: CGFloat(bitmap[3]) / 255) } +} #endif diff --git a/Sources/OversizeCore/Extensions/Swift/Array+Extension.swift b/Sources/OversizeCore/Extensions/Swift/Array+Extension.swift index 8c9fc23..df7697f 100644 --- a/Sources/OversizeCore/Extensions/Swift/Array+Extension.swift +++ b/Sources/OversizeCore/Extensions/Swift/Array+Extension.swift @@ -143,6 +143,16 @@ extension Array: @retroactive RawRepresentable where Element: Codable { } } +public extension Array { + func element(_ index: Int) -> Element? { + if index >= 0, index < count { + self[index] + } else { + nil + } + } +} + public extension BidirectionalCollection where Iterator.Element: Equatable { func after(_ item: Iterator.Element, loop: Bool = false) -> Element? { if let itemIndex = firstIndex(of: item) { @@ -172,3 +182,9 @@ public extension BidirectionalCollection where Iterator.Element: Equatable { return nil } } + +public extension Array { + func compacted() -> [T] where Element == T? { + compactMap { $0 } + } +} diff --git a/Sources/OversizeCore/Extensions/Swift/Date+Extension.swift b/Sources/OversizeCore/Extensions/Swift/Date+Extension.swift index 173db25..32898c5 100644 --- a/Sources/OversizeCore/Extensions/Swift/Date+Extension.swift +++ b/Sources/OversizeCore/Extensions/Swift/Date+Extension.swift @@ -160,15 +160,15 @@ public extension Date { public extension Date { var displayTodayLabelOrDate: String { if Calendar.current.isDateInToday(self) { - return "Today" + "Today" } else if Calendar.current.isDateInTomorrow(self) { - return "Tomorrow" + "Tomorrow" } else if Calendar.current.isDateInYesterday(self) { - return "Yesterday" + "Yesterday" } else if Calendar.current.component(.year, from: self) == Calendar.current.component(.year, from: Date()) { - return "\(formatted(.dateTime.day().month(.wide)))" + "\(formatted(.dateTime.day().month(.wide)))" } else { - return "\(formatted(.dateTime.day().month(.wide).year()))" + "\(formatted(.dateTime.day().month(.wide).year()))" } } } diff --git a/Sources/OversizeCore/Extensions/Swift/String+Extension.swift b/Sources/OversizeCore/Extensions/Swift/String+Extension.swift index 945d91e..a8aa1b3 100644 --- a/Sources/OversizeCore/Extensions/Swift/String+Extension.swift +++ b/Sources/OversizeCore/Extensions/Swift/String+Extension.swift @@ -137,52 +137,52 @@ extension String { #if os(iOS) || os(tvOS) || os(watchOS) - extension String { - func getAttributedStringFromHtml(font: UIFont, color: UIColor) -> NSAttributedString? { - guard let data = data(using: String.Encoding.utf16, allowLossyConversion: false) else { - return nil - } +extension String { + func getAttributedStringFromHtml(font: UIFont, color: UIColor) -> NSAttributedString? { + guard let data = data(using: String.Encoding.utf16, allowLossyConversion: false) else { + return nil + } - guard let attributedString = try? NSMutableAttributedString( - data: data, - options: [ - .documentType: NSAttributedString.DocumentType.html, - .characterEncoding: String.Encoding.utf8.rawValue, - ], - documentAttributes: nil - ) else { - return nil - } + guard let attributedString = try? NSMutableAttributedString( + data: data, + options: [ + .documentType: NSAttributedString.DocumentType.html, + .characterEncoding: String.Encoding.utf8.rawValue, + ], + documentAttributes: nil + ) else { + return nil + } - attributedString.addAttributes( - [ - .font: font, - .foregroundColor: color, - ], - range: NSRange(location: 0, length: attributedString.length) - ) + attributedString.addAttributes( + [ + .font: font, + .foregroundColor: color, + ], + range: NSRange(location: 0, length: attributedString.length) + ) - return attributedString - } + return attributedString } +} - public extension String { - func size(font: UIFont) -> CGSize { - let originalString = self as NSString - return originalString.size(withAttributes: [NSAttributedString.Key.font: font]) - } +public extension String { + func size(font: UIFont) -> CGSize { + let originalString = self as NSString + return originalString.size(withAttributes: [NSAttributedString.Key.font: font]) + } - func width(font: UIFont) -> CGFloat { - size(font: font).width - } + func width(font: UIFont) -> CGFloat { + size(font: font).width } +} - public extension NSAttributedString { - func height(width: CGFloat) -> CGFloat { - let constraintRect: CGSize = .init(width: width, height: CGFloat.greatestFiniteMagnitude) - let boundingBox = boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil) - return ceil(boundingBox.height) + 1 - } +public extension NSAttributedString { + func height(width: CGFloat) -> CGFloat { + let constraintRect: CGSize = .init(width: width, height: CGFloat.greatestFiniteMagnitude) + let boundingBox = boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil) + return ceil(boundingBox.height) + 1 } +} #endif diff --git a/Sources/OversizeCore/Extensions/View/View+Extension.swift b/Sources/OversizeCore/Extensions/View/View+Extension.swift index 71f7fb1..b227f7c 100644 --- a/Sources/OversizeCore/Extensions/View/View+Extension.swift +++ b/Sources/OversizeCore/Extensions/View/View+Extension.swift @@ -4,29 +4,29 @@ // #if os(iOS) - import SwiftUI - import UIKit +import SwiftUI +import UIKit - public extension UIView { - var renderedImage: UIImage { - let rect = bounds - UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0) - let context: CGContext = UIGraphicsGetCurrentContext()! - layer.render(in: context) - let capturedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()! - UIGraphicsEndImageContext() - return capturedImage - } +public extension UIView { + var renderedImage: UIImage { + let rect = bounds + UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0) + let context: CGContext = UIGraphicsGetCurrentContext()! + layer.render(in: context) + let capturedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()! + UIGraphicsEndImageContext() + return capturedImage } +} - public extension View { - func takeScreenshot(origin: CGPoint, size: CGSize) -> UIImage { - let window: UIWindow = .init(frame: CGRect(origin: origin, size: size)) - let hosting: UIHostingController = .init(rootView: self) - hosting.view.frame = window.frame - window.addSubview(hosting.view) - window.makeKeyAndVisible() - return hosting.view.renderedImage - } +public extension View { + func takeScreenshot(origin: CGPoint, size: CGSize) -> UIImage { + let window: UIWindow = .init(frame: CGRect(origin: origin, size: size)) + let hosting: UIHostingController = .init(rootView: self) + hosting.view.frame = window.frame + window.addSubview(hosting.view) + window.makeKeyAndVisible() + return hosting.view.renderedImage } +} #endif diff --git a/Sources/OversizeCore/Global/Log.swift b/Sources/OversizeCore/Global/Log.swift index 52d7996..70cc730 100644 --- a/Sources/OversizeCore/Global/Log.swift +++ b/Sources/OversizeCore/Global/Log.swift @@ -7,112 +7,112 @@ import Foundation public func log(_ objects: Any...) { #if DEBUG - log(objects.map { "\($0)" }.joined(separator: ", ")) + log(objects.map { "\($0)" }.joined(separator: ", ")) #endif } public func log(_ object: Any?) { #if DEBUG - if let object { - log(object) - } else { - log(String(describing: object)) - } + if let object { + log(object) + } else { + log(String(describing: object)) + } #endif } @inlinable public func log(_ text: String, terminator: String? = nil) { #if DEBUG - terminator == nil ? print(text) : print(text, terminator: terminator!) + terminator == nil ? print(text) : print(text, terminator: terminator!) #endif } public func logWithTime(_ text: String, terminator: String? = nil) { #if DEBUG - let textTime: String = Date().formatted(.dateTime) - let textWithTime = "🕓 [\(textTime)] \(text)" - terminator == nil ? print(textWithTime) : print(textWithTime, terminator: terminator!) + let textTime: String = Date().formatted(.dateTime) + let textWithTime = "🕓 [\(textTime)] \(text)" + terminator == nil ? print(textWithTime) : print(textWithTime, terminator: terminator!) #endif } @inlinable public func logDebug(_ text: String, terminator: String? = nil) { #if DEBUG - terminator == nil ? print("âšĒ [DEBUG] \(text)") : print("âšĒ [DEBUG] \(text)", terminator: terminator!) + terminator == nil ? print("âšĒ [DEBUG] \(text)") : print("âšĒ [DEBUG] \(text)", terminator: terminator!) #endif } @inlinable public func logNotice(_ text: String, terminator: String? = nil) { #if DEBUG - terminator == nil ? print("🛎ī¸ [NOTICE] \(text)") : print("🛎ī¸ [NOTICE] \(text)", terminator: terminator!) + terminator == nil ? print("🛎ī¸ [NOTICE] \(text)") : print("🛎ī¸ [NOTICE] \(text)", terminator: terminator!) #endif } @inlinable public func logInfo(_ text: String, terminator: String? = nil) { #if DEBUG - terminator == nil ? print("ℹī¸ [INFO] \(text)") : print("ℹī¸ [INFO] \(text)", terminator: terminator!) + terminator == nil ? print("ℹī¸ [INFO] \(text)") : print("ℹī¸ [INFO] \(text)", terminator: terminator!) #endif } @_disfavoredOverload @inlinable public func logSuccess(_ text: String, terminator: String? = nil) { #if DEBUG - terminator == nil ? print("✅ [SUCCESS] \(text)") : print("✅ [SUCCESS] \(text)", terminator: terminator!) + terminator == nil ? print("✅ [SUCCESS] \(text)") : print("✅ [SUCCESS] \(text)", terminator: terminator!) #endif } public func logSuccess(_ text: String, object: Any?) { #if DEBUG - print("✅ [SUCCESS] \(text), object:\n") - log(object) + print("✅ [SUCCESS] \(text), object:\n") + log(object) #endif } @inlinable public func logWarning(_ text: String, terminator: String? = nil) { #if DEBUG - terminator == nil ? print("⚠ī¸ [WARNING] \(text)") : print("⚠ī¸ [WARNING] \(text)", terminator: terminator!) + terminator == nil ? print("⚠ī¸ [WARNING] \(text)") : print("⚠ī¸ [WARNING] \(text)", terminator: terminator!) #endif } @inlinable public func logError(_ text: String, terminator: String? = nil) { #if DEBUG - terminator == nil ? print("🔴 [ERROR] \(text)") : print("🔴 [ERROR] \(text)", terminator: terminator!) + terminator == nil ? print("🔴 [ERROR] \(text)") : print("🔴 [ERROR] \(text)", terminator: terminator!) #endif } @inlinable public func logError(_ text: String, error: Error, terminator: String? = nil) { #if DEBUG - terminator == nil ? print("🔴 [ERROR] \(text):\n\(error.localizedDescription)") : print("🔴 [ERROR] \(text):\n\(error.localizedDescription)", terminator: terminator!) + terminator == nil ? print("🔴 [ERROR] \(text):\n\(error.localizedDescription)\n\(error)") : print("🔴 [ERROR] \(text):\n\(error.localizedDescription)", terminator: terminator!) #endif } @inlinable public func logError(_ text: String, error: String, terminator: String? = nil) { #if DEBUG - terminator == nil ? print("🔴 [ERROR] \(text):\n\(error)") : print("🔴 [ERROR] \(text):\n\(error)", terminator: terminator!) + terminator == nil ? print("🔴 [ERROR] \(text):\n\(error)") : print("🔴 [ERROR] \(text):\n\(error)", terminator: terminator!) #endif } @inlinable public func logDeleted(_ text: String, terminator: String? = nil) { #if DEBUG - terminator == nil ? print("🗑ī¸ [DELETED] \(text)") : print("🗑ī¸ [DELETED] \(text)", terminator: terminator!) + terminator == nil ? print("🗑ī¸ [DELETED] \(text)") : print("🗑ī¸ [DELETED] \(text)", terminator: terminator!) #endif } @inlinable public func logData(_ text: String, terminator: String? = nil) { #if DEBUG - terminator == nil ? print("đŸ’Ŋ [DATA] \(text)") : print("đŸ’Ŋ [DATA] \(text)", terminator: terminator!) + terminator == nil ? print("đŸ’Ŋ [DATA] \(text)") : print("đŸ’Ŋ [DATA] \(text)", terminator: terminator!) #endif } @inlinable public func logUrl(_ text: String? = nil, url: URL?, terminator: String? = nil) { #if DEBUG - guard let url else { - log("🔗 [URL] Nil or not valid URL", terminator: terminator) - return - } - if let text { - url.isFileURL ? log("📁 [URL] \(text):\n\(url.path)", terminator: terminator) : log("🌐 [URL] \(text):\n\(url.absoluteString)", terminator: terminator) - } else { - url.isFileURL ? log("📁 [URL] \(url.path)", terminator: terminator) : log("🌐 [URL] \(url.absoluteString)", terminator: terminator) - } + guard let url else { + log("🔗 [URL] Nil or not valid URL", terminator: terminator) + return + } + if let text { + url.isFileURL ? log("📁 [URL] \(text):\n\(url.path)", terminator: terminator) : log("🌐 [URL] \(text):\n\(url.absoluteString)", terminator: terminator) + } else { + url.isFileURL ? log("📁 [URL] \(url.path)", terminator: terminator) : log("🌐 [URL] \(url.absoluteString)", terminator: terminator) + } #endif }