NetNewsWire/Shared/Extensions/ArticleStringFormatter.swift
2024-09-24 22:31:21 -07:00

121 lines
2.8 KiB
Swift

//
// ArticleStringFormatter.swift
// NetNewsWire
//
// Created by Brent Simmons on 8/31/15.
// Copyright © 2015 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import Articles
import Parser
@MainActor struct ArticleStringFormatter {
private static var feedNameCache = [String: String]()
private static var titleCache = [String: String]()
private static var summaryCache = [String: String]()
private static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
return formatter
}()
private static let timeFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .short
return formatter
}()
static func emptyCaches() {
feedNameCache = [String: String]()
titleCache = [String: String]()
summaryCache = [String: String]()
}
static func truncatedFeedName(_ feedName: String) -> String {
if let cachedFeedName = feedNameCache[feedName] {
return cachedFeedName
}
let maxFeedNameLength = 100
if feedName.count < maxFeedNameLength {
feedNameCache[feedName] = feedName
return feedName
}
let s = (feedName as NSString).substring(to: maxFeedNameLength)
feedNameCache[feedName] = s
return s
}
static func truncatedTitle(_ article: Article, forHTML: Bool = false) -> String {
guard let title = article.sanitizedTitle(forHTML: forHTML) else {
return ""
}
if let cachedTitle = titleCache[title] {
return cachedTitle
}
var s = title.replacingOccurrences(of: "\n", with: "")
s = s.replacingOccurrences(of: "\r", with: "")
s = s.replacingOccurrences(of: "\t", with: "")
if !forHTML {
s = HTMLEntityDecoder.decodedString(s)
}
s = s.trimmingWhitespace
s = s.collapsingWhitespace
let maxLength = 1000
if s.count < maxLength {
titleCache[title] = s
return s
}
s = (s as NSString).substring(to: maxLength)
titleCache[title] = s
return s
}
static func attributedTruncatedTitle(_ article: Article) -> NSAttributedString {
let title = truncatedTitle(article, forHTML: true)
let attributed = NSAttributedString(html: title)
return attributed
}
static func truncatedSummary(_ article: Article) -> String {
guard let body = article.body else {
return ""
}
let key = article.articleID + article.accountID
if let cachedBody = summaryCache[key] {
return cachedBody
}
var s = body
s = s.strippingHTML(maxCharacters: 250)
s = HTMLEntityDecoder.decodedString(s)
s = s.trimmingWhitespace
s = s.collapsingWhitespace
if s == "Comments" { // Hacker News.
s = ""
}
summaryCache[key] = s
return s
}
static func dateString(_ date: Date) -> String {
if Calendar.dateIsToday(date) {
return timeFormatter.string(from: date)
}
return dateFormatter.string(from: date)
}
}