import Foundation private let formatter: DateFormatter = { let formatter = DateFormatter() formatter.dateStyle = .short return formatter }() /// Reports violations as HTML. struct HTMLReporter: Reporter { // MARK: - Reporter Conformance static let identifier = "html" static let isRealtime = false static let description = "Reports violations as HTML." static func generateReport(_ violations: [StyleViolation]) -> String { generateReport(violations, swiftlintVersion: Version.current.value, dateString: formatter.string(from: Date())) } // MARK: - Internal // swiftlint:disable:next function_body_length internal static func generateReport(_ violations: [StyleViolation], swiftlintVersion: String, dateString: String) -> String { let rows = violations.enumerated() .map { generateSingleRow(for: $1, at: $0 + 1) } .joined(separator: "\n") let fileCount = Set(violations.compactMap(\.location.file)).count let warningCount = violations.filter({ $0.severity == .warning }).count let errorCount = violations.filter({ $0.severity == .error }).count return """ \t
\t\t \t\t \t\t \t\t \t\t \t\t| \t\t\t\t\t\tSerial No. \t\t\t\t\t | \t\t\t\t\t\t\t\t\t\t\tFile \t\t\t\t\t | \t\t\t\t\t\t\t\t\t\t\tLocation \t\t\t\t\t | \t\t\t\t\t\t\t\t\t\t\tSeverity \t\t\t\t\t | \t\t\t\t\t\t\t\t\t\t\tMessage \t\t\t\t\t | \t\t\t\t
|---|
| Total files with violations | \t\t\t\t\t\(fileCount) | \t\t\t\t
| Total warnings | \t\t\t\t\t\(warningCount) | \t\t\t\t
| Total errors | \t\t\t\t\t\(errorCount) | \t\t\t\t
\t\t\tCreated with \t\t\tSwiftLint \t\t\t\(swiftlintVersion) on \(dateString) \t\t
\t """ } // MARK: - Private private static func generateSingleRow(for violation: StyleViolation, at index: Int) -> String { let severity: String = violation.severity.rawValue.capitalized let location = violation.location let file: String = (violation.location.relativeFile ?? "