<commit_before>//
//  MarkdownLink.swift
//  Pods
//
//  Created by <NAME> on 18/07/16.
//
//

import UIKit

open class MarkdownLink: MarkdownLinkElement {
  
  fileprivate static let regex = "\\[[^\\[]*?\\]\\([^\\)]*\\)"
  
  open var font: UIFont?
  open var color: UIColor?
  
  open var regex: String {
    return MarkdownLink.regex
  }
  
  open func regularExpression() throws -> NSRegularExpression {
    return try NSRegularExpression(pattern: regex, options: .dotMatchesLineSeparators)
  }
  
  public init(font: UIFont? = nil, color: UIColor? = UIColor.blue) {
    self.font = font
    self.color = color
  }
  
  
  open func formatText(_ attributedString: NSMutableAttributedString, range: NSRange,
                         link: String) {
    guard let encodedLink = link.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed)
      else {
      return
    }
    guard let url = URL(string: link) ?? URL(string: encodedLink) else { return }
    attributedString.addAttribute(NSAttributedString.Key.link, value: url, range: range)
  }
  
  open func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString) {
    let nsString = attributedString.string as NSString
    let linkStartInResult = nsString
      .range(of: "(", options: .backwards, range: match.range).location
    let linkRange =
      NSRange(location: linkStartInResult,
              length: match.range.length + match.range.location - linkStartInResult - 1)
    let linkURLString = nsString
      .substring(with: NSRange(location: linkRange.location + 1, length: linkRange.length - 1))
    
    // deleting trailing markdown
    // needs to be called before formattingBlock to support modification of length
    attributedString.deleteCharacters(in: NSRange(location: linkRange.location - 1,
      length: linkRange.length + 2))
    
    // deleting leading markdown
    // needs to be called before formattingBlock to provide a stable range
    attributedString.deleteCharacters(in: NSRange(location: match.range.location, length: 1))
    let formatRange = NSRange(location: match.range.location,
                              length: linkStartInResult - match.range.location - 2)
    formatText(attributedString, range: formatRange, link: linkURLString)
    addAttributes(attributedString, range: formatRange, link: linkURLString)
  }
  
  open func addAttributes(_ attributedString: NSMutableAttributedString, range: NSRange,
                            link: String) {
    attributedString.addAttributes(attributes, range: range)
  }
}<commit_msg>Fixed a bug with parentheses on the urls.<commit_after>//
//  MarkdownLink.swift
//  Pods
//
//  Created by <NAME> on 18/07/16.
//
//

import UIKit

open class MarkdownLink: MarkdownLinkElement {
  
  fileprivate static let regex = "\\[[^\\]]+\\]\\(\\S+(?=\\))\\)"
  
  // This regex is eager if does not count even trailing Parentheses.
  fileprivate static let onlyLinkRegex = "\\(\\S+(?=\\))\\)"
  
  open var font: UIFont?
  open var color: UIColor?
  
  open var regex: String {
    return MarkdownLink.regex
  }
  
  open func regularExpression() throws -> NSRegularExpression {
    return try NSRegularExpression(pattern: regex, options: .dotMatchesLineSeparators)
  }
  
  public init(font: UIFont? = nil, color: UIColor? = UIColor.blue) {
    self.font = font
    self.color = color
  }
  
  
  open func formatText(_ attributedString: NSMutableAttributedString, range: NSRange,
                         link: String) {
    guard let encodedLink = link.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed)
      else {
      return
    }
    guard let url = URL(string: link) ?? URL(string: encodedLink) else { return }
    attributedString.addAttribute(NSAttributedString.Key.link, value: url, range: range)
  }
  
  open func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString) {
    let nsString = (attributedString.string as NSString)
    let urlString = nsString.substring(with: match.range)
    
    guard let onlyLinkRegex = try? NSRegularExpression(pattern: MarkdownLink.onlyLinkRegex, options: .dotMatchesLineSeparators) else {
      return
    }
    
    guard let linkMatch = onlyLinkRegex.firstMatch(in: urlString,
                     options: .withoutAnchoringBounds,
                     range: NSRange(location: 0, length: urlString.count)) else {
                      return
    }

    let urlLinkAbsoluteStart = match.range.location
    
    let linkURLString = nsString
      .substring(with: NSRange(location: urlLinkAbsoluteStart + linkMatch.range.location + 1, length: linkMatch.range.length - 2))
    
    // deleting trailing markdown
    // needs to be called before formattingBlock to support modification of length
    let trailingMarkdownRange = NSRange(location: urlLinkAbsoluteStart + linkMatch.range.location - 1, length: linkMatch.range.length + 1)
    attributedString.deleteCharacters(in: trailingMarkdownRange)
    
    // deleting leading markdown
    // needs to be called before formattingBlock to provide a stable range
    let leadingMarkdownRange = NSRange(location: match.range.location, length: 1)
    attributedString.deleteCharacters(in: leadingMarkdownRange)
    
    let formatRange = NSRange(location: match.range.location,
                              length: linkMatch.range.location - 2)
    
    formatText(attributedString, range: formatRange, link: linkURLString)
    addAttributes(attributedString, range: formatRange, link: linkURLString)
  }
  
  open func addAttributes(_ attributedString: NSMutableAttributedString, range: NSRange,
                            link: String) {
    attributedString.addAttributes(attributes, range: range)
  }
}
{'fraction_non_alphanumeric': 0.0948065528058557, 'fraction_numerical': 0.004531195538515162, 'mean_word_length': 3.1139784946236557, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, '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': '2759055', 'n_tokens_mistral': 1673, 'n_tokens_neox': 1612, 'n_words': 431}