enum PageContentAnomaly { case failedToLoadContent(Error) case missingFile(String) case missingPage(String) case missingTag(String) case unknownCommand(String) case invalidCommandArguments(command: ShorthandMarkdownKey, arguments: [String]) } extension PageContentAnomaly: Identifiable { var id: String { switch self { case .failedToLoadContent: return "load-failed" case .missingFile(let string): return "missing-file-\(string)" case .missingPage(let string): return "missing-page-\(string)" case .missingTag(let string): return "missing-tag-\(string)" case .unknownCommand(let string): return "unknown-command-\(string)" case .invalidCommandArguments(let command, let arguments): return "invalid-arguments-\(command)-\(arguments.joined(separator: "-"))" } } } extension PageContentAnomaly { enum Severity: String, CaseIterable { case warning case error } var severity: Severity { switch self { case .failedToLoadContent: return .error case .missingFile, .missingPage, .missingTag, .unknownCommand, .invalidCommandArguments: return .warning } } } extension PageContentAnomaly: CustomStringConvertible { var description: String { switch self { case .failedToLoadContent(let error): return "Failed to load content: \(error)" case .missingFile(let string): return "Missing file \(string)" case .missingPage(let string): return "Missing page \(string)" case .missingTag(let string): return "Missing tag \(string)" case .unknownCommand(let string): return "Unknown command \(string)" case .invalidCommandArguments(let command, let arguments): return "Invalid command arguments for \(command): \(arguments)" } } }