Ensure correct text formatting
This commit is contained in:
parent
0fee70eeba
commit
aae0e51154
|
@ -145,9 +145,10 @@ a:hover {
|
||||||
line-height: 1.4em;
|
line-height: 1.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-el .media-body {
|
.status-content.media-body {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container, .item {
|
.container, .item {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import strutils, strformat, htmlgen, xmltree
|
import strutils, strformat, htmlgen, xmltree, times
|
||||||
import regex
|
import regex
|
||||||
|
|
||||||
import ./types, ./utils
|
import ./types, ./utils
|
||||||
|
@ -8,7 +8,7 @@ from unicode import Rune, `$`
|
||||||
const
|
const
|
||||||
urlRegex = re"((https?|ftp)://(-\.)?([^\s/?\.#]+\.?)+(/[^\s]*)?)"
|
urlRegex = re"((https?|ftp)://(-\.)?([^\s/?\.#]+\.?)+(/[^\s]*)?)"
|
||||||
emailRegex = re"([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)"
|
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/[^ ]+"
|
picRegex = re"pic.twitter.com/[^ ]+"
|
||||||
cardRegex = re"(https?://)?cards.twitter.com/[^ ]+"
|
cardRegex = re"(https?://)?cards.twitter.com/[^ ]+"
|
||||||
ellipsisRegex = re" ?…"
|
ellipsisRegex = re" ?…"
|
||||||
|
@ -48,14 +48,14 @@ proc reUsernameToLink*(m: RegexMatch; s: string): string =
|
||||||
pretext & toLink("/" & username, "@" & username)
|
pretext & toLink("/" & username, "@" & username)
|
||||||
|
|
||||||
proc linkifyText*(text: string): string =
|
proc linkifyText*(text: string): string =
|
||||||
result = text.stripText()
|
result = xmltree.escape(stripText(text))
|
||||||
result = result.replace("\n", "<br>")
|
|
||||||
result = result.replace(ellipsisRegex, "")
|
result = result.replace(ellipsisRegex, "")
|
||||||
result = result.replace(usernameRegex, reUsernameToLink)
|
|
||||||
result = result.replace(emailRegex, reEmailToLink)
|
result = result.replace(emailRegex, reEmailToLink)
|
||||||
result = result.replace(urlRegex, reUrlToLink)
|
result = result.replace(urlRegex, reUrlToLink)
|
||||||
result = result.replace(re"([A-z0-9\):;.])<a", "$1 <a")
|
result = result.replace("\n", "<br>")
|
||||||
result = result.replace(re"</a>\s+([;.,\)])", "</a>$1")
|
result = result.replace(usernameRegex, reUsernameToLink)
|
||||||
|
result = result.replace(re"([^\s\(\n])<a", "$1 <a")
|
||||||
|
result = result.replace(re"</a>\s+([;.,!\)']|')", "</a>$1")
|
||||||
|
|
||||||
proc stripTwitterUrls*(text: string): string =
|
proc stripTwitterUrls*(text: string): string =
|
||||||
result = text
|
result = text
|
||||||
|
@ -92,3 +92,6 @@ proc pageTitle*(profile: Profile): string =
|
||||||
|
|
||||||
proc pageTitle*(page: string): string =
|
proc pageTitle*(page: string): string =
|
||||||
&"{page} | Nitter"
|
&"{page} | Nitter"
|
||||||
|
|
||||||
|
proc getTime*(tweet: Tweet): string =
|
||||||
|
tweet.time.format("d/M/yyyy', ' HH:mm:ss")
|
||||||
|
|
|
@ -44,7 +44,7 @@ proc parseQuote*(quote: XmlNode): Quote =
|
||||||
result = Quote(
|
result = Quote(
|
||||||
id: quote.getAttr("data-item-id"),
|
id: quote.getAttr("data-item-id"),
|
||||||
link: quote.getAttr("href"),
|
link: quote.getAttr("href"),
|
||||||
text: quote.selectText(".QuoteTweet-text").stripTwitterUrls()
|
text: getQuoteText(quote)
|
||||||
)
|
)
|
||||||
|
|
||||||
result.profile = Profile(
|
result.profile = Profile(
|
||||||
|
|
|
@ -42,6 +42,17 @@ proc emojify*(node: XmlNode) =
|
||||||
for i in node.querySelectorAll(".Emoji"):
|
for i in node.querySelectorAll(".Emoji"):
|
||||||
i.add newText(i.getAttr("alt"))
|
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 =
|
proc getTweetText*(tweet: XmlNode): string =
|
||||||
let
|
let
|
||||||
selector = ".tweet-text > a.twitter-timeline-link.u-hidden"
|
selector = ".tweet-text > a.twitter-timeline-link.u-hidden"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#
|
#
|
||||||
#proc renderMain*(body: string; title="Nitter"): string =
|
#proc renderMain*(body: string; title="Nitter"): string =
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>${xmltree.escape(title)}</title>
|
<title>${xmltree.escape(title)}</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/style.css">
|
<link rel="stylesheet" type="text/css" href="/style.css">
|
||||||
|
|
|
@ -21,9 +21,7 @@
|
||||||
${linkUser(tweet.profile, class="username")}
|
${linkUser(tweet.profile, class="username")}
|
||||||
</div>
|
</div>
|
||||||
<span class="heading-right">
|
<span class="heading-right">
|
||||||
<a href="${tweet.link}" class="timeago faint-link">
|
<a href="${tweet.link}" title="${tweet.getTime()}">${tweet.shortTime}</a>
|
||||||
<time title="${tweet.time.format("d/M/yyyy', ' HH:mm:ss")}">${tweet.shortTime}</time>
|
|
||||||
</a>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,7 +30,7 @@
|
||||||
#proc renderQuote(quote: Quote): string =
|
#proc renderQuote(quote: Quote): string =
|
||||||
#let hasMedia = quote.thumb.isSome() or quote.sensitive
|
#let hasMedia = quote.thumb.isSome() or quote.sensitive
|
||||||
<div class="quote">
|
<div class="quote">
|
||||||
<div class="quote-container" href="${quote.link}">
|
<div class="quote-container">
|
||||||
<a class="quote-link" href="${quote.link}"></a>
|
<a class="quote-link" href="${quote.link}"></a>
|
||||||
#if hasMedia:
|
#if hasMedia:
|
||||||
<div class="quote-media-container">
|
<div class="quote-media-container">
|
||||||
|
@ -56,7 +54,7 @@
|
||||||
${linkUser(quote.profile, class="fullname")}
|
${linkUser(quote.profile, class="fullname")}
|
||||||
${linkUser(quote.profile, class="username")}
|
${linkUser(quote.profile, class="username")}
|
||||||
</div>
|
</div>
|
||||||
<div class="quote-text">${linkifyText(xmltree.escape(quote.text))}</div>
|
<div class="quote-text">${linkifyText(quote.text)}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
#end proc
|
#end proc
|
||||||
|
@ -65,7 +63,7 @@
|
||||||
#let groups = if tweet.photos.len > 2: tweet.photos.distribute(2) else: @[tweet.photos]
|
#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: ""
|
#let display = if groups.len == 1 and groups[0].len == 1: "display: table-caption;" else: ""
|
||||||
#var first = true
|
#var first = true
|
||||||
<div class="attachments media-body" style="${display}">
|
<div class="attachments" style="${display}">
|
||||||
#for photos in groups:
|
#for photos in groups:
|
||||||
#let margin = if not first: "margin-top: .25em;" else: ""
|
#let margin = if not first: "margin-top: .25em;" else: ""
|
||||||
#let flex = if photos.len > 1 or groups.len > 1: "display: flex;" else: ""
|
#let flex = if photos.len > 1 or groups.len > 1: "display: flex;" else: ""
|
||||||
|
@ -87,7 +85,7 @@
|
||||||
#end proc
|
#end proc
|
||||||
#
|
#
|
||||||
#proc renderVideo(video: Video): string =
|
#proc renderVideo(video: Video): string =
|
||||||
<div class="attachments media-body">
|
<div class="attachments">
|
||||||
<div class="gallery-row" style="max-height: unset;">
|
<div class="gallery-row" style="max-height: unset;">
|
||||||
<div class="attachment image">
|
<div class="attachment image">
|
||||||
<video poster=${video.thumb.getSigUrl("pic")} autoplay muted loop></video>
|
<video poster=${video.thumb.getSigUrl("pic")} autoplay muted loop></video>
|
||||||
|
@ -100,7 +98,7 @@
|
||||||
#end proc
|
#end proc
|
||||||
#
|
#
|
||||||
#proc renderGif(gif: Gif): string =
|
#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="gallery-row" style="max-height: unset;">
|
||||||
<div class="attachment image">
|
<div class="attachment image">
|
||||||
<video class="gif" poster=${gif.thumb.getSigUrl("pic")} autoplay muted loop>
|
<video class="gif" poster=${gif.thumb.getSigUrl("pic")} autoplay muted loop>
|
||||||
|
@ -127,9 +125,7 @@
|
||||||
<div class="status-body">
|
<div class="status-body">
|
||||||
${renderHeading(tweet)}
|
${renderHeading(tweet)}
|
||||||
<div class="status-content-wrapper">
|
<div class="status-content-wrapper">
|
||||||
<div class="status-content media-body">
|
<div class="status-content media-body">${linkifyText(tweet.text)}</div>
|
||||||
${linkifyText(xmltree.escape(tweet.text))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
#if tweet.photos.len > 0:
|
#if tweet.photos.len > 0:
|
||||||
${renderMediaGroup(tweet)}
|
${renderMediaGroup(tweet)}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<div class="profile-bio">
|
<div class="profile-bio">
|
||||||
#if profile.bio.len > 0:
|
#if profile.bio.len > 0:
|
||||||
<div class="profile-bio">
|
<div class="profile-bio">
|
||||||
<p>${linkifyText(xmltree.escape(profile.bio))}</p>
|
<p>${linkifyText(profile.bio)}</p>
|
||||||
</div>
|
</div>
|
||||||
#end if
|
#end if
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue