mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-21 05:39:01 +00:00
99 lines
5.3 KiB
Swift
99 lines
5.3 KiB
Swift
import Foundation
|
|
import Display
|
|
|
|
private let controlStartCharactersSet = CharacterSet(charactersIn: "[")
|
|
private let controlCharactersSet = CharacterSet(charactersIn: "[]()*_-\\")
|
|
|
|
final class MarkdownAttributeSet {
|
|
let font: UIFont
|
|
let textColor: UIColor
|
|
|
|
init(font: UIFont, textColor: UIColor) {
|
|
self.font = font
|
|
self.textColor = textColor
|
|
}
|
|
}
|
|
|
|
final class MarkdownAttributes {
|
|
let body: MarkdownAttributeSet
|
|
let link: MarkdownAttributeSet
|
|
let linkAttribute: (String) -> (String, Any)?
|
|
|
|
init(body: MarkdownAttributeSet, link: MarkdownAttributeSet, linkAttribute: @escaping (String) -> (String, Any)?) {
|
|
self.body = body
|
|
self.link = link
|
|
self.linkAttribute = linkAttribute
|
|
}
|
|
}
|
|
|
|
func escapedPlaintextForMarkdown(_ string: String) -> String {
|
|
let nsString = string as NSString
|
|
var remainingRange = NSMakeRange(0, nsString.length)
|
|
let result = NSMutableString()
|
|
while true {
|
|
let range = nsString.rangeOfCharacter(from: controlCharactersSet, options: [], range: remainingRange)
|
|
if range.location != NSNotFound {
|
|
result.append("\\")
|
|
result.append(nsString.substring(with: NSMakeRange(range.location, range.length)))
|
|
remainingRange = NSMakeRange(range.location + range.length, remainingRange.location + remainingRange.length - (range.location + range.length))
|
|
} else {
|
|
result.append(nsString.substring(with: NSMakeRange(remainingRange.location, remainingRange.length)))
|
|
break
|
|
}
|
|
}
|
|
return result as String
|
|
}
|
|
|
|
func parseMarkdownIntoAttributedString(_ string: String, attributes: MarkdownAttributes) -> NSAttributedString {
|
|
let nsString = string as NSString
|
|
let result = NSMutableAttributedString()
|
|
var remainingRange = NSMakeRange(0, nsString.length)
|
|
|
|
let bodyAttributes: [String: Any] = [NSFontAttributeName: attributes.body.font, NSForegroundColorAttributeName: attributes.body.textColor]
|
|
|
|
while true {
|
|
let range = nsString.rangeOfCharacter(from: controlStartCharactersSet, options: [], range: remainingRange)
|
|
if range.location != NSNotFound {
|
|
if range.location != remainingRange.location {
|
|
result.append(NSAttributedString(string: nsString.substring(with: NSMakeRange(remainingRange.location, range.location - remainingRange.location)), attributes: bodyAttributes))
|
|
remainingRange = NSMakeRange(range.location, remainingRange.location + remainingRange.length - range.location)
|
|
}
|
|
|
|
let character = nsString.character(at: range.location)
|
|
if character == UInt16(("[" as UnicodeScalar).value) {
|
|
remainingRange = NSMakeRange(range.location + range.length, remainingRange.location + remainingRange.length - (range.location + range.length))
|
|
if let (parsedLinkText, parsedLinkContents) = parseLink(string: nsString, remainingRange: &remainingRange) {
|
|
var linkAttributes: [String: Any] = [NSFontAttributeName: attributes.link.font, NSForegroundColorAttributeName: attributes.link.textColor]
|
|
if let (attributeName, attributeValue) = attributes.linkAttribute(parsedLinkContents) {
|
|
linkAttributes[attributeName] = attributeValue
|
|
}
|
|
result.append(NSAttributedString(string: parsedLinkText, attributes: linkAttributes))
|
|
}
|
|
}
|
|
} else {
|
|
if remainingRange.length != 0 {
|
|
result.append(NSAttributedString(string: nsString.substring(with: NSMakeRange(remainingRange.location, remainingRange.length)), attributes: bodyAttributes))
|
|
}
|
|
break
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
private func parseLink(string: NSString, remainingRange: inout NSRange) -> (text: String, contents: String)? {
|
|
var localRemainingRange = remainingRange
|
|
let closingSquareBraceRange = string.range(of: "]", options: [], range: localRemainingRange)
|
|
if closingSquareBraceRange.location != NSNotFound {
|
|
localRemainingRange = NSMakeRange(closingSquareBraceRange.location + closingSquareBraceRange.length, remainingRange.location + remainingRange.length - (closingSquareBraceRange.location + closingSquareBraceRange.length))
|
|
let openingRoundBraceRange = string.range(of: "(", options: [], range: localRemainingRange)
|
|
let closingRoundBraceRange = string.range(of: ")", options: [], range: localRemainingRange)
|
|
if openingRoundBraceRange.location == closingSquareBraceRange.location + closingSquareBraceRange.length && closingRoundBraceRange.location != NSNotFound && openingRoundBraceRange.location < closingRoundBraceRange.location {
|
|
let linkText = string.substring(with: NSMakeRange(remainingRange.location, closingSquareBraceRange.location - remainingRange.location))
|
|
let linkContents = string.substring(with: NSMakeRange(openingRoundBraceRange.location + openingRoundBraceRange.length, closingRoundBraceRange.location - (openingRoundBraceRange.location + openingRoundBraceRange.length)))
|
|
remainingRange = NSMakeRange(closingRoundBraceRange.location + closingRoundBraceRange.length, remainingRange.location + remainingRange.length - (closingRoundBraceRange.location + closingRoundBraceRange.length))
|
|
return (linkText, linkContents)
|
|
}
|
|
}
|
|
return nil
|
|
}
|