diff --git a/public/style.css b/public/style.css
index a7ea7ee..5105315 100644
--- a/public/style.css
+++ b/public/style.css
@@ -3,6 +3,7 @@ body {
color: #f8f8f2;
margin: 0;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+ font-size: 14px;
}
#tweets {
@@ -575,6 +576,11 @@ nav {
font-weight: bold;
}
+video {
+ height: 100%;
+ width: 100%;
+}
+
.video-overlay {
width: 100%;
height: 100%;
@@ -594,7 +600,67 @@ nav {
font-size: 20px;
}
-video {
+.quote {
+ margin-top: 10px;
+ border: solid 1px #404040;
+ border-radius: 10px;
+ padding: 6px;
+ background-color: #121212;
+}
+
+.quote:hover {
+ border-color: #808080;
+}
+
+.quote-container {
+ position: relative;
+ overflow: auto;
+}
+
+.quote-link {
height: 100%;
width: 100%;
+ left: 0;
+ top: 0;
+ position: absolute;
+}
+
+.quote-text {
+ overflow: hidden;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+}
+
+.quote-media-container {
+ display: flex;
+ align-items: center;
+ overflow: hidden;
+ max-height: 102px;
+ width: 102px;
+ float: left;
+ margin-right: 7px;
+ border-radius: 7px;
+}
+
+.quote-media {
+ display: flex;
+ justify-content: center;
+}
+
+.quote-media img {
+ width: 100%;
+ height: 100%;
+}
+
+.quote-badge {
+ background: rgba(0,0,0,0.25);
+ border-radius: 4px;
+ bottom: 8px;
+ box-sizing: border-box;
+ color: #fffffff0;
+ left: 8px;
+ position: absolute;
+ z-index: 1;
+ line-height: 16px;
+ padding: 2px;
}
diff --git a/src/formatters.nim b/src/formatters.nim
index 046d1df..0c1f16d 100644
--- a/src/formatters.nim
+++ b/src/formatters.nim
@@ -21,7 +21,7 @@ proc toLink*(url, text: string; class="timeline-link"): string =
proc reUrlToLink*(m: RegexMatch; s: string): string =
let url = s[m.group(0)[0]]
- toLink(url, " " & shortLink(url))
+ toLink(url, shortLink(url))
proc reEmailToLink*(m: RegexMatch; s: string): string =
let url = s[m.group(0)[0]]
@@ -44,12 +44,13 @@ proc reUsernameToLink*(m: RegexMatch; s: string): string =
pretext & toLink("/" & username, "@" & username)
proc linkifyText*(text: string): string =
- result = text.replace("\n", "
")
+ result = text.strip()
+ result = result.replace("\n", "
")
result = result.replace(ellipsisRegex, "")
result = result.replace(usernameRegex, reUsernameToLink)
result = result.replace(emailRegex, reEmailToLink)
result = result.replace(urlRegex, reUrlToLink)
- result = result.replace(re"\s+", " ")
+ result = result.replace(re"([A-z0-9])", "$1 ")
result = result.replace(re" ([.,\)])", "$1")
proc stripTwitterUrls*(text: string): string =
diff --git a/src/parser.nim b/src/parser.nim
index 0e0cd38..585334e 100644
--- a/src/parser.nim
+++ b/src/parser.nim
@@ -1,7 +1,7 @@
import xmltree, sequtils, strtabs, strutils, strformat, json
import nimquery
-import ./types, ./parserutils
+import ./types, ./parserutils, ./formatters
proc parsePopupProfile*(node: XmlNode): Profile =
let profile = node.querySelector(".profile-card")
@@ -16,6 +16,7 @@ proc parsePopupProfile*(node: XmlNode): Profile =
protected: isProtected(profile),
banner: getBanner(profile)
)
+
result.getPopupStats(profile)
proc parseIntentProfile*(profile: XmlNode): Profile =
@@ -28,6 +29,7 @@ proc parseIntentProfile*(profile: XmlNode): Profile =
protected: not profile.querySelector("li.protected").isNil,
banner: getBanner(profile)
)
+
result.getIntentStats(profile)
proc parseTweetProfile*(profile: XmlNode): Profile =
@@ -38,20 +40,21 @@ proc parseTweetProfile*(profile: XmlNode): Profile =
verified: isVerified(profile)
)
-proc parseQuote*(tweet: XmlNode): Tweet =
- let tweet = tweet.querySelector(".QuoteTweet-innerContainer")
- result = Tweet(
- id: tweet.getAttr("data-item-id"),
- link: tweet.getAttr("href"),
- text: tweet.selectText(".QuoteTweet-text")
+proc parseQuote*(quote: XmlNode): Quote =
+ result = Quote(
+ id: quote.getAttr("data-item-id"),
+ link: quote.getAttr("href"),
+ text: quote.selectText(".QuoteTweet-text").stripTwitterUrls()
)
result.profile = Profile(
- fullname: tweet.getAttr("data-screen-name"),
- username: tweet.selectText(".QuteTweet-fullname"),
- verified: isVerified(tweet)
+ fullname: quote.selectText(".QuoteTweet-fullname"),
+ username: quote.getAttr("data-screen-name"),
+ verified: isVerified(quote)
)
+ result.getQuoteMedia(quote)
+
proc parseTweet*(tweet: XmlNode): Tweet =
result = Tweet(
id: tweet.getAttr("data-item-id"),
@@ -71,6 +74,10 @@ proc parseTweet*(tweet: XmlNode): Tweet =
result.retweetBy = some(by)
result.retweetId = some(tweet.getAttr("data-retweet-id"))
+ let quote = tweet.querySelector(".QuoteTweet-innerContainer")
+ if not quote.isNil:
+ result.quote = some(parseQuote(quote))
+
proc parseTweets*(node: XmlNode): Tweets =
if node.isNil: return
node.querySelectorAll(".tweet").map(parseTweet)
diff --git a/src/parserutils.nim b/src/parserutils.nim
index 7fe11a5..c1bfb67 100644
--- a/src/parserutils.nim
+++ b/src/parserutils.nim
@@ -34,10 +34,10 @@ proc getUsername*(profile: XmlNode; selector: string): string =
proc getTweetText*(tweet: XmlNode): string =
let selector = ".tweet-text > a.twitter-timeline-link.u-hidden"
let link = tweet.selectAttr(selector, "data-expanded-url")
- var text =tweet.selectText(".tweet-text")
+ var text = tweet.selectText(".tweet-text")
if link.len > 0 and link in text:
- text = text.replace(link, " " & link)
+ text = text.replace(link, "")
stripTwitterUrls(text)
@@ -114,3 +114,12 @@ proc getTweetMedia*(tweet: Tweet; node: XmlNode) =
tweet.gif = some(getGif(player.querySelector(".PlayableMedia-player")))
elif "video" in player.getAttr("class"):
tweet.video = some(Video())
+
+proc getQuoteMedia*(quote: var Quote; node: XmlNode) =
+ let media = node.querySelector(".QuoteMedia")
+ if not media.isNil:
+ quote.thumb = some(media.selectAttr("img", "src"))
+
+ let badge = node.querySelector(".AdaptiveMedia-badgeText")
+ if not badge.isNil:
+ quote.badge = some(badge.innerText())
diff --git a/src/types.nim b/src/types.nim
index cca8e8d..85a0b0b 100644
--- a/src/types.nim
+++ b/src/types.nim
@@ -43,12 +43,13 @@ type
url*: string
thumb*: string
- Quote* = ref object
+ Quote* = object
id*: string
profile*: Profile
link*: string
text*: string
- video*: Option[Video]
+ thumb*: Option[string]
+ badge*: Option[string]
Tweet* = ref object
id*: string
diff --git a/src/views/tweet.nim b/src/views/tweet.nim
index 8f22e37..c5c2461 100644
--- a/src/views/tweet.nim
+++ b/src/views/tweet.nim
@@ -29,6 +29,30 @@
#end proc
#
+#proc renderQuote(quote: Quote): string =
+#let hasMedia = quote.thumb.isSome()
+