slices.nim 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import std/[macros, htmlgen, unicode]
  2. import ".."/../[formatters, utils]
  3. type
  4. ReplaceSliceKind* = enum
  5. rkRemove, rkUrl, rkHashtag, rkMention
  6. ReplaceSlice* = object
  7. slice*: Slice[int]
  8. kind*: ReplaceSliceKind
  9. url*, display*: string
  10. proc cmp*(x, y: ReplaceSlice): int = cmp(x.slice.a, y.slice.b)
  11. proc dedupSlices*(s: var seq[ReplaceSlice]) =
  12. var
  13. len = s.len
  14. i = 0
  15. while i < len:
  16. var j = i + 1
  17. while j < len:
  18. if s[i].slice.a == s[j].slice.a:
  19. s.del j
  20. dec len
  21. else:
  22. inc j
  23. inc i
  24. proc extractHashtags*(result: var seq[ReplaceSlice]; slice: Slice[int]) =
  25. result.add ReplaceSlice(kind: rkHashtag, slice: slice)
  26. proc extractUrls*[T](result: var seq[ReplaceSlice]; entity: T;
  27. textLen: int; hideTwitter = false) =
  28. let
  29. link = entity.expandedUrl
  30. slice = entity.indices
  31. if hideTwitter and slice.b.succ >= textLen and link.isTwitterUrl:
  32. if slice.a < textLen:
  33. result.add ReplaceSlice(kind: rkRemove, slice: slice)
  34. else:
  35. result.add ReplaceSlice(kind: rkUrl, url: link,
  36. display: link.shortLink, slice: slice)
  37. proc replacedWith*(runes: seq[Rune]; repls: openArray[ReplaceSlice];
  38. textSlice: Slice[int]): string =
  39. template extractLowerBound(i: int; idx): int =
  40. if i > 0: repls[idx].slice.b.succ else: textSlice.a
  41. result = newStringOfCap(runes.len)
  42. for i, rep in repls:
  43. result.add $runes[extractLowerBound(i, i - 1) ..< rep.slice.a]
  44. case rep.kind
  45. of rkHashtag:
  46. let
  47. name = $runes[rep.slice.a.succ .. rep.slice.b]
  48. symbol = $runes[rep.slice.a]
  49. result.add a(symbol & name, href = "/search?q=%23" & name)
  50. of rkMention:
  51. result.add a($runes[rep.slice], href = rep.url, title = rep.display)
  52. of rkUrl:
  53. result.add a(rep.display, href = rep.url)
  54. of rkRemove:
  55. discard
  56. let rest = extractLowerBound(repls.len, ^1) ..< textSlice.b
  57. if rest.a <= rest.b:
  58. result.add $runes[rest]