Преглед изворни кода

Support image alt text

Fixes #559
Zed пре 7 месеци
родитељ
комит
1c06a67afd

+ 12 - 4
src/parser.nim

@@ -139,7 +139,10 @@ proc parseLegacyMediaEntities(js: JsonNode; result: var Tweet) =
     for m in jsMedia:
       case m.getTypeName:
       of "photo":
-        result.photos.add m{"media_url_https"}.getImageStr
+        result.photos.add Photo(
+          url: m{"media_url_https"}.getImageStr,
+          altText: m{"ext_alt_text"}.getStr
+        )
       of "video":
         result.video = some(parseVideo(m))
         with user, m{"additional_media_info", "source_user"}:
@@ -165,7 +168,10 @@ proc parseMediaEntities(js: JsonNode; result: var Tweet) =
       with mediaInfo, mediaEntity{"media_results", "result", "media_info"}:
         case mediaInfo.getTypeName
         of "ApiImage":
-          result.photos.add mediaInfo{"original_img_url"}.getImageStr
+          result.photos.add Photo(
+            url: mediaInfo{"original_img_url"}.getImageStr,
+            altText: mediaInfo{"alt_text"}.getStr
+          )
         of "ApiVideo":
           let status = mediaEntity{"media_results", "result", "media_availability_v2", "status"}
           result.video = some Video(
@@ -332,11 +338,13 @@ proc parseTweet(js: JsonNode; jsCard: JsonNode = newJNull()): Tweet =
     let name = jsCard{"name"}.getStr
     if "poll" in name:
       if "image" in name:
-        result.photos.add jsCard{"binding_values", "image_large"}.getImageVal
+        result.photos.add Photo(
+          url: jsCard{"binding_values", "image_large"}.getImageVal
+        )
 
       result.poll = some parsePoll(jsCard)
     elif name == "amplify":
-      result.video = some(parsePromoVideo(jsCard{"binding_values"}))
+      result.video = some parsePromoVideo(jsCard{"binding_values"})
     else:
       result.card = some parseCard(jsCard, js{"entities", "urls"})
 

+ 1 - 1
src/parserutils.nim

@@ -333,7 +333,7 @@ proc expandNoteTweetEntities*(tweet: Tweet; js: JsonNode) =
 
 proc extractGalleryPhoto*(t: Tweet): GalleryPhoto =
   let url =
-    if t.photos.len > 0: t.photos[0]
+    if t.photos.len > 0: t.photos[0].url
     elif t.video.isSome: get(t.video).thumb
     elif t.gif.isSome: get(t.gif).thumb
     elif t.card.isSome: get(t.card).image

+ 1 - 1
src/routes/status.nim

@@ -44,7 +44,7 @@ proc createStatusRouter*(cfg: Config) =
         desc = conv.tweet.text
 
       var
-        images = conv.tweet.photos
+        images = conv.tweet.photos.mapIt(it.url)
         video = ""
 
       if conv.tweet.video.isSome():

+ 31 - 4
src/sass/tweet/media.scss

@@ -4,7 +4,6 @@
   display: flex;
   flex-direction: row;
   flex-wrap: nowrap;
-  align-items: center;
   overflow: hidden;
   flex-grow: 1;
   max-height: 379.5px;
@@ -13,7 +12,7 @@
 
   .still-image {
     width: 100%;
-    display: flex;
+    align-self: center;
   }
 }
 
@@ -58,7 +57,6 @@
 .still-image {
   max-height: 379.5px;
   max-width: 533px;
-  justify-content: center;
 
   img {
     object-fit: cover;
@@ -69,8 +67,37 @@
   }
 }
 
+.alt-text {
+  margin: 0px;
+  padding: 11px 7px;
+  box-sizing: border-box;
+  position: absolute;
+  bottom: 10px;
+  left: 10px;
+  width: 2.98em;
+  max-height: 25px;
+  white-space: pre;
+  overflow: hidden;
+  border-radius: 10px;
+  color: var(--fg_color);
+  font-size: 12px;
+  font-weight: bold;
+  background: rgba(0, 0, 0, 0.5);
+  backdrop-filter: blur(12px);
+}
+
+.alt-text:hover {
+  padding: 7px;
+  width: Min(230px, calc(100% - 10px * 2));
+  max-height: calc(100% - 10px);
+  line-height: 1.2em;
+  white-space: pre-wrap;
+  transition-duration: 0.4s;
+  transition-property: max-height;
+}
+
 .image {
-  display: inline-block;
+  display: flex;
 }
 
 // .single-image {

+ 5 - 1
src/types.nim

@@ -137,6 +137,10 @@ type
     url*: string
     thumb*: string
 
+  Photo* = object
+    url*: string
+    altText*: string
+
   GalleryPhoto* = object
     url*: string
     tweetId*: string
@@ -217,7 +221,7 @@ type
     poll*: Option[Poll]
     gif*: Option[Gif]
     video*: Option[Video]
-    photos*: seq[string]
+    photos*: seq[Photo]
 
   Tweets* = seq[Tweet]
 

+ 1 - 1
src/views/general.nim

@@ -50,7 +50,7 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
   let opensearchUrl = getUrlPrefix(cfg) & "/opensearch"
 
   buildHtml(head):
-    link(rel="stylesheet", type="text/css", href="/css/style.css?v=23")
+    link(rel="stylesheet", type="text/css", href="/css/style.css?v=24")
     link(rel="stylesheet", type="text/css", href="/css/fontello.css?v=4")
 
     if theme.len > 0:

+ 2 - 2
src/views/renderutils.nim

@@ -97,9 +97,9 @@ proc genNumberInput*(pref, label, state, placeholder: string; class=""; autofocu
       label(`for`=pref): text label
     input(name=pref, `type`="number", placeholder=p, value=state, autofocus=(autofocus and state.len == 0), min=min, step="1")
 
-proc genImg*(url: string; class=""): VNode =
+proc genImg*(url: string; class=""; alt=""): VNode =
   buildHtml():
-    img(src=getPicUrl(url), class=class, alt="", loading="lazy")
+    img(src=getPicUrl(url), class=class, alt=alt, loading="lazy")
 
 proc getTabClass*(query: Query; tab: QueryKind): string =
   if query.kind == tab: "tab-item active"

+ 1 - 1
src/views/rss.nimf

@@ -56,7 +56,7 @@ Twitter feed for: ${desc}. Generated by ${getUrlPrefix(cfg)}
 <p>${text.replace("\n", "<br>\n")}</p>
 #if tweet.photos.len > 0:
 #  for photo in tweet.photos:
-<img src="${urlPrefix}${getPicUrl(photo)}" style="max-width:250px;" />
+<img src="${urlPrefix}${getPicUrl(photo.url)}" style="max-width:250px;" />
 #  end for
 #elif tweet.video.isSome:
 <a href="${urlPrefix}${tweet.getLink}">

+ 6 - 4
src/views/tweet.nim

@@ -50,10 +50,12 @@ proc renderAlbum(tweet: Tweet): VNode =
         for photo in photos:
           tdiv(class="attachment image"):
             let
-              named = "name=" in photo
-              small = if named: photo else: photo & smallWebp
-            a(href=getOrigPicUrl(photo), class="still-image", target="_blank"):
-              genImg(small)
+              named = "name=" in photo.url
+              small = if named: photo.url else: photo.url & smallWebp
+            a(href=getOrigPicUrl(photo.url), class="still-image", target="_blank"):
+              genImg(small, alt=photo.altText)
+            if photo.altText.len > 0:
+              p(class="alt-text"): text "ALT  " & photo.altText
 
 proc isPlaybackEnabled(prefs: Prefs; playbackType: VideoType): bool =
   case playbackType