Kaynağa Gözat

Ensure correct text formatting

Zed 7 yıl önce
ebeveyn
işleme
aae0e51154

+ 2 - 1
public/style.css

@@ -145,9 +145,10 @@ a:hover {
     line-height: 1.4em;
 }
 
-.status-el .media-body {
+.status-content.media-body {
     flex: 1;
     padding: 0;
+    white-space: pre-wrap;
 }
 
 .container, .item {

+ 10 - 7
src/formatters.nim

@@ -1,4 +1,4 @@
-import strutils, strformat, htmlgen, xmltree
+import strutils, strformat, htmlgen, xmltree, times
 import regex
 
 import ./types, ./utils
@@ -8,7 +8,7 @@ from unicode import Rune, `$`
 const
   urlRegex = re"((https?|ftp)://(-\.)?([^\s/?\.#]+\.?)+(/[^\s]*)?)"
   emailRegex = re"([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)"
-  usernameRegex = re"(^|[^\S\n]|\.)@([A-z0-9_]+)"
+  usernameRegex = re"(^|[^\S\n]|\.|>)@([A-z0-9_]+)"
   picRegex = re"pic.twitter.com/[^ ]+"
   cardRegex = re"(https?://)?cards.twitter.com/[^ ]+"
   ellipsisRegex = re" ?…"
@@ -48,14 +48,14 @@ proc reUsernameToLink*(m: RegexMatch; s: string): string =
   pretext & toLink("/" & username, "@" & username)
 
 proc linkifyText*(text: string): string =
-  result = text.stripText()
-  result = result.replace("\n", "<br>")
+  result = xmltree.escape(stripText(text))
   result = result.replace(ellipsisRegex, "")
-  result = result.replace(usernameRegex, reUsernameToLink)
   result = result.replace(emailRegex, reEmailToLink)
   result = result.replace(urlRegex, reUrlToLink)
-  result = result.replace(re"([A-z0-9\):;.])<a", "$1 <a")
-  result = result.replace(re"</a>\s+([;.,\)])", "</a>$1")
+  result = result.replace("\n", "<br>")
+  result = result.replace(usernameRegex, reUsernameToLink)
+  result = result.replace(re"([^\s\(\n])<a", "$1 <a")
+  result = result.replace(re"</a>\s+([;.,!\)']|&apos;)", "</a>$1")
 
 proc stripTwitterUrls*(text: string): string =
   result = text
@@ -92,3 +92,6 @@ proc pageTitle*(profile: Profile): string =
 
 proc pageTitle*(page: string): string =
   &"{page} | Nitter"
+
+proc getTime*(tweet: Tweet): string =
+  tweet.time.format("d/M/yyyy', ' HH:mm:ss")

+ 1 - 1
src/parser.nim

@@ -44,7 +44,7 @@ proc parseQuote*(quote: XmlNode): Quote =
   result = Quote(
     id:   quote.getAttr("data-item-id"),
     link: quote.getAttr("href"),
-    text: quote.selectText(".QuoteTweet-text").stripTwitterUrls()
+    text: getQuoteText(quote)
   )
 
   result.profile = Profile(

+ 11 - 0
src/parserutils.nim

@@ -42,6 +42,17 @@ proc emojify*(node: XmlNode) =
   for i in node.querySelectorAll(".Emoji"):
     i.add newText(i.getAttr("alt"))
 
+proc getQuoteText*(tweet: XmlNode): string =
+  let
+    text = tweet.querySelector(".QuoteTweet-text")
+    hasEmojis = not text.querySelector(".Emoji").isNil
+
+  if hasEmojis:
+    emojify(text)
+
+  result = stripText(selectText(text, ".tweet-text"))
+  result = stripTwitterUrls(result)
+
 proc getTweetText*(tweet: XmlNode): string =
   let
     selector = ".tweet-text > a.twitter-timeline-link.u-hidden"

+ 1 - 1
src/views/general.nimf

@@ -3,7 +3,7 @@
 #
 #proc renderMain*(body: string; title="Nitter"): string =
 <!DOCTYPE html>
-<html>
+<html lang="en">
   <head>
     <title>${xmltree.escape(title)}</title>
     <link rel="stylesheet" type="text/css" href="/style.css">

+ 7 - 11
src/views/tweet.nimf

@@ -21,9 +21,7 @@
       ${linkUser(tweet.profile, class="username")}
     </div>
     <span class="heading-right">
-      <a href="${tweet.link}" class="timeago faint-link">
-        <time title="${tweet.time.format("d/M/yyyy', ' HH:mm:ss")}">${tweet.shortTime}</time>
-      </a>
+      <a href="${tweet.link}" title="${tweet.getTime()}">${tweet.shortTime}</a>
     </span>
   </div>
 </div>
@@ -32,7 +30,7 @@
 #proc renderQuote(quote: Quote): string =
 #let hasMedia = quote.thumb.isSome() or quote.sensitive
 <div class="quote">
-  <div class="quote-container" href="${quote.link}">
+  <div class="quote-container">
     <a class="quote-link" href="${quote.link}"></a>
     #if hasMedia:
     <div class="quote-media-container">
@@ -56,7 +54,7 @@
       ${linkUser(quote.profile, class="fullname")}
       ${linkUser(quote.profile, class="username")}
     </div>
-    <div class="quote-text">${linkifyText(xmltree.escape(quote.text))}</div>
+    <div class="quote-text">${linkifyText(quote.text)}</div>
   </div>
 </div>
 #end proc
@@ -65,7 +63,7 @@
 #let groups = if tweet.photos.len > 2: tweet.photos.distribute(2) else: @[tweet.photos]
 #let display = if groups.len == 1 and groups[0].len == 1: "display: table-caption;" else: ""
 #var first = true
-<div class="attachments media-body" style="${display}">
+<div class="attachments" style="${display}">
 #for photos in groups:
   #let margin = if not first: "margin-top: .25em;" else: ""
   #let flex = if photos.len > 1 or groups.len > 1: "display: flex;" else: ""
@@ -87,7 +85,7 @@
 #end proc
 #
 #proc renderVideo(video: Video): string =
-<div class="attachments media-body">
+<div class="attachments">
   <div class="gallery-row" style="max-height: unset;">
     <div class="attachment image">
     <video poster=${video.thumb.getSigUrl("pic")} autoplay muted loop></video>
@@ -100,7 +98,7 @@
 #end proc
 #
 #proc renderGif(gif: Gif): string =
-<div class="attachments media-body media-gif">
+<div class="attachments media-gif">
   <div class="gallery-row" style="max-height: unset;">
     <div class="attachment image">
       <video class="gif" poster=${gif.thumb.getSigUrl("pic")} autoplay muted loop>
@@ -127,9 +125,7 @@
   <div class="status-body">
     ${renderHeading(tweet)}
     <div class="status-content-wrapper">
-      <div class="status-content media-body">
-        ${linkifyText(xmltree.escape(tweet.text))}
-      </div>
+      <div class="status-content media-body">${linkifyText(tweet.text)}</div>
     </div>
     #if tweet.photos.len > 0:
     ${renderMediaGroup(tweet)}

+ 1 - 1
src/views/user.nimf

@@ -18,7 +18,7 @@
     <div class="profile-bio">
       #if profile.bio.len > 0:
       <div class="profile-bio">
-        <p>${linkifyText(xmltree.escape(profile.bio))}</p>
+        <p>${linkifyText(profile.bio)}</p>
       </div>
       #end if
     </div>