Implement twitter entities as html links

This commit is contained in:
Maurice Parker 2020-04-19 20:29:43 -05:00
parent 45f56f01e3
commit f305cc50e2
5 changed files with 70 additions and 34 deletions

View File

@ -18,14 +18,11 @@ struct TwitterHashtag: Codable, TwitterEntity {
case indices = "indices" case indices = "indices"
} }
var startIndex: Int {
if let indices = indices, indices.count > 0 {
return indices[0] - 1
}
return 0
}
func renderAsHTML() -> String { func renderAsHTML() -> String {
return "" var html = String()
if let text = text {
html += "<a href=\"https://twitter.com/search?q=%23\(text)\">#\(text)</a>"
}
return html
} }
} }

View File

@ -13,19 +13,21 @@ struct TwitterMention: Codable, TwitterEntity {
let name: String? let name: String?
let indices: [Int]? let indices: [Int]?
let screenName: String? let screenName: String?
let expandedURL: String?
let idStr: String? let idStr: String?
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case name = "url" case name = "url"
case indices = "indices" case indices = "indices"
case screenName = "screen_name" case screenName = "screen_name"
case expandedURL = "expandedURL"
case idStr = "idStr" case idStr = "idStr"
} }
func renderAsHTML() -> String { func renderAsHTML() -> String {
return "" var html = String()
if let screenName = screenName {
html += "<a href=\"https://twitter.com/\(screenName)\">@\(screenName)</a>"
}
return html
} }
} }

View File

@ -41,16 +41,6 @@ final class TwitterStatus: Codable {
return "\(userURL)/status/\(idStr)" return "\(userURL)/status/\(idStr)"
} }
var displayText: String? {
if let text = fullText, let displayRange = displayTextRange, displayRange.count > 1,
let startIndex = text.index(text.startIndex, offsetBy: displayRange[0], limitedBy: text.endIndex),
let endIndex = text.index(text.startIndex, offsetBy: displayRange[1], limitedBy: text.endIndex) {
return String(text[startIndex..<endIndex])
} else {
return fullText
}
}
func renderAsText() -> String? { func renderAsText() -> String? {
let statusToRender = retweetedStatus != nil ? retweetedStatus! : self let statusToRender = retweetedStatus != nil ? retweetedStatus! : self
return statusToRender.displayText return statusToRender.displayText
@ -66,8 +56,54 @@ final class TwitterStatus: Codable {
return renderAsOriginalHTML(topLevel: topLevel) return renderAsOriginalHTML(topLevel: topLevel)
} }
}
private extension TwitterStatus {
var displayText: String? {
if let text = fullText, let displayRange = displayTextRange, displayRange.count > 1,
let startIndex = text.index(text.startIndex, offsetBy: displayRange[0], limitedBy: text.endIndex),
let endIndex = text.index(text.startIndex, offsetBy: displayRange[1], limitedBy: text.endIndex) {
return String(text[startIndex..<endIndex])
} else {
return fullText
}
}
var displayHTML: String? {
if let text = fullText, let displayRange = displayTextRange, displayRange.count > 1,
let displayStartIndex = text.index(text.startIndex, offsetBy: displayRange[0], limitedBy: text.endIndex),
let displayEndIndex = text.index(text.startIndex, offsetBy: displayRange[1], limitedBy: text.endIndex),
let entities = entities?.combineAndSort() {
var html = String()
var prevIndex = displayStartIndex
for entity in entities {
if let entityStartIndex = text.index(text.startIndex, offsetBy: entity.startIndex, limitedBy: text.endIndex),
let entityEndIndex = text.index(text.startIndex, offsetBy: entity.endIndex, limitedBy: text.endIndex) {
if prevIndex < entityStartIndex {
html += String(text[prevIndex..<entityStartIndex])
}
html += entity.renderAsHTML()
prevIndex = entityEndIndex
}
}
if prevIndex < displayEndIndex {
html += String(text[prevIndex..<displayEndIndex])
}
return html
} else {
return displayText
}
}
func renderAsTweetHTML(_ status: TwitterStatus, topLevel: Bool) -> String { func renderAsTweetHTML(_ status: TwitterStatus, topLevel: Bool) -> String {
var html = "<div>\(status.displayText ?? "")</div>" var html = "<div>\(status.displayHTML ?? "")</div>"
if !topLevel, let createdAt = status.createdAt { if !topLevel, let createdAt = status.createdAt {
let dateFormatter = DateFormatter() let dateFormatter = DateFormatter()

View File

@ -18,15 +18,12 @@ struct TwitterSymbol: Codable, TwitterEntity {
case indices = "indices" case indices = "indices"
} }
var startIndex: Int {
if let indices = indices, indices.count > 0 {
return indices[0] - 1
}
return 0
}
func renderAsHTML() -> String { func renderAsHTML() -> String {
return "" var html = String()
if let name = name {
html += "<a href=\"https://twitter.com/search?q=%24\(name)\">$\(name)</a>"
}
return html
} }
} }

View File

@ -18,12 +18,16 @@ struct TwitterURL: Codable, TwitterEntity {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case url = "url" case url = "url"
case indices = "indices" case indices = "indices"
case displayURL = "displayURL" case displayURL = "display_url"
case expandedURL = "expandedURL" case expandedURL = "expanded_url"
} }
func renderAsHTML() -> String { func renderAsHTML() -> String {
return "" var html = String()
if let expandedURL = expandedURL, let displayURL = displayURL {
html += "<a href=\"\(expandedURL)\">\(displayURL)</a>"
}
return html
} }
} }