<commit_before>//
//  ArticleStringFormatter.swift
//  NetNewsWire
//
//  Created by <NAME> on 8/31/15.
//  Copyright © 2015 Ranchero Software, LLC. All rights reserved.
//

import Foundation
import Articles
import RSParser

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 = s.rsparser_stringByDecodingHTMLEntities()
		}

		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 data = title.data(using: .utf8)!
		let attributed = NSAttributedString(html: data, documentAttributes: nil)!
		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.rsparser_stringByDecodingHTMLEntities()
		s = s.strippingHTML(maxCharacters: 250)
		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)
	}
}

<commit_msg>Re-add use of custom initializer<commit_after>//
//  ArticleStringFormatter.swift
//  NetNewsWire
//
//  Created by <NAME> on 8/31/15.
//  Copyright © 2015 Ranchero Software, LLC. All rights reserved.
//

import Foundation
import Articles
import RSParser

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 = s.rsparser_stringByDecodingHTMLEntities()
		}

		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.rsparser_stringByDecodingHTMLEntities()
		s = s.strippingHTML(maxCharacters: 250)
		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)
	}
}


{'fraction_non_alphanumeric': 0.10597500428008902, 'fraction_numerical': 0.00667693888032871, 'mean_word_length': 3.776778413736713, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1451556', 'n_tokens_mistral': 2135, 'n_tokens_neox': 1850, 'n_words': 510}