Multiple front-end fixes (#2247)

Fixes:
* Sanitize user-provided content in HTML (Fixes #2193)
* Fix encoding of search query in prev/next pages (Fixes #2229)
* Fix some issues introduced with #2196:
   - Fix alignment of all <h3> elements (Move the inline style from the parent to the <h3> element)
   - Add missing comma on 'dir' HTML attribute (Typo introduced by PR #2196)

Code cleaning:
* Remove unnecessary 'each_sclice' + 'each' double loop in ECR files
* Clean the player's <source> list generation code (in player.ecr)
This commit is contained in:
Samantaz Fox 2021-07-15 23:01:36 +02:00 committed by GitHub
parent 3e5c353298
commit 56ebef4352
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 161 additions and 169 deletions

View file

@ -312,6 +312,8 @@ def template_youtube_comments(comments, locale, thin_mode, is_replies = false)
author_thumbnail = "" author_thumbnail = ""
end end
author_name = HTML.escape(child["author"].as_s)
html << <<-END_HTML html << <<-END_HTML
<div class="pure-g" style="width:100%"> <div class="pure-g" style="width:100%">
<div class="channel-profile pure-u-4-24 pure-u-md-2-24"> <div class="channel-profile pure-u-4-24 pure-u-md-2-24">
@ -320,7 +322,7 @@ def template_youtube_comments(comments, locale, thin_mode, is_replies = false)
<div class="pure-u-20-24 pure-u-md-22-24"> <div class="pure-u-20-24 pure-u-md-22-24">
<p> <p>
<b> <b>
<a class="#{child["authorIsChannelOwner"] == true ? "channel-owner" : ""}" href="#{child["authorUrl"]}">#{child["author"]}</a> <a class="#{child["authorIsChannelOwner"] == true ? "channel-owner" : ""}" href="#{child["authorUrl"]}">#{author_name}</a>
</b> </b>
<p style="white-space:pre-wrap">#{child["contentHtml"]}</p> <p style="white-space:pre-wrap">#{child["contentHtml"]}</p>
END_HTML END_HTML

View file

@ -9,13 +9,13 @@
<%= translate(locale, "Token") %> <%= translate(locale, "Token") %>
</h3> </h3>
</div> </div>
<div class="pure-u-1-3" style="text-align:center"> <div class="pure-u-1-3">
<h3> <h3 style="text-align:center">
<a href="/token_manager"><%= translate(locale, "Token manager") %></a> <a href="/token_manager"><%= translate(locale, "Token manager") %></a>
</h3> </h3>
</div> </div>
<div class="pure-u-1-3" style="text-align:right"> <div class="pure-u-1-3">
<h3> <h3 style="text-align:right">
<a href="/preferences"><%= translate(locale, "Preferences") %></a> <a href="/preferences"><%= translate(locale, "Preferences") %></a>
</h3> </h3>
</div> </div>

View file

@ -1,6 +1,9 @@
<% ucid = channel.ucid %>
<% author = HTML.escape(channel.author) %>
<% content_for "header" do %> <% content_for "header" do %>
<title><%= channel.author %> - Invidious</title> <title><%= author %> - Invidious</title>
<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/channel/<%= channel.ucid %>" /> <link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/channel/<%= ucid %>" />
<% end %> <% end %>
<% if channel.banner %> <% if channel.banner %>
@ -17,12 +20,12 @@
<div class="pure-u-2-3"> <div class="pure-u-2-3">
<div class="channel-profile"> <div class="channel-profile">
<img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>"> <img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>">
<span><%= channel.author %></span> <span><%= author %></span>
</div> </div>
</div> </div>
<div class="pure-u-1-3" style="text-align:right"> <div class="pure-u-1-3">
<h3 style="text-align:right"> <h3 style="text-align:right">
<a href="/feed/channel/<%= channel.ucid %>"><i class="icon ion-logo-rss"></i></a> <a href="/feed/channel/<%= ucid %>"><i class="icon ion-logo-rss"></i></a>
</h3> </h3>
</div> </div>
</div> </div>
@ -34,15 +37,13 @@
</div> </div>
<div class="h-box"> <div class="h-box">
<% ucid = channel.ucid %>
<% author = channel.author %>
<% sub_count_text = number_to_short_text(channel.sub_count) %> <% sub_count_text = number_to_short_text(channel.sub_count) %>
<%= rendered "components/subscribe_widget" %> <%= rendered "components/subscribe_widget" %>
</div> </div>
<div class="pure-g h-box"> <div class="pure-g h-box">
<div class="pure-u-1-3"> <div class="pure-u-1-3">
<a href="https://www.youtube.com/channel/<%= channel.ucid %>"><%= translate(locale, "View channel on YouTube") %></a> <a href="https://www.youtube.com/channel/<%= ucid %>"><%= translate(locale, "View channel on YouTube") %></a>
<div class="pure-u-1 pure-md-1-3"> <div class="pure-u-1 pure-md-1-3">
<a href="/redirect?referer=<%= env.get?("current_page") %>"><%= translate(locale, "Switch Invidious Instance") %></a> <a href="/redirect?referer=<%= env.get?("current_page") %>"><%= translate(locale, "Switch Invidious Instance") %></a>
</div> </div>
@ -55,12 +56,12 @@
<% if channel.auto_generated %> <% if channel.auto_generated %>
<b><%= translate(locale, "Playlists") %></b> <b><%= translate(locale, "Playlists") %></b>
<% else %> <% else %>
<a href="/channel/<%= channel.ucid %>/playlists"><%= translate(locale, "Playlists") %></a> <a href="/channel/<%= ucid %>/playlists"><%= translate(locale, "Playlists") %></a>
<% end %> <% end %>
</div> </div>
<div class="pure-u-1 pure-md-1-3"> <div class="pure-u-1 pure-md-1-3">
<% if channel.tabs.includes? "community" %> <% if channel.tabs.includes? "community" %>
<a href="/channel/<%= channel.ucid %>/community"><%= translate(locale, "Community") %></a> <a href="/channel/<%= ucid %>/community"><%= translate(locale, "Community") %></a>
<% end %> <% end %>
</div> </div>
</div> </div>
@ -72,7 +73,7 @@
<% if sort_by == sort %> <% if sort_by == sort %>
<b><%= translate(locale, sort) %></b> <b><%= translate(locale, sort) %></b>
<% else %> <% else %>
<a href="/channel/<%= channel.ucid %>?page=<%= page %>&sort_by=<%= sort %>"> <a href="/channel/<%= ucid %>?page=<%= page %>&sort_by=<%= sort %>">
<%= translate(locale, sort) %> <%= translate(locale, sort) %>
</a> </a>
<% end %> <% end %>
@ -87,17 +88,15 @@
</div> </div>
<div class="pure-g"> <div class="pure-g">
<% items.each_slice(4) do |slice| %> <% items.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %> <% end %>
<% end %>
<% end %>
</div> </div>
<div class="pure-g h-box"> <div class="pure-g h-box">
<div class="pure-u-1 pure-u-lg-1-5"> <div class="pure-u-1 pure-u-lg-1-5">
<% if page > 1 %> <% if page > 1 %>
<a href="/channel/<%= channel.ucid %>?page=<%= page - 1 %><% if sort_by != "newest" %>&sort_by=<%= HTML.escape(sort_by) %><% end %>"> <a href="/channel/<%= ucid %>?page=<%= page - 1 %><% if sort_by != "newest" %>&sort_by=<%= HTML.escape(sort_by) %><% end %>">
<%= translate(locale, "Previous page") %> <%= translate(locale, "Previous page") %>
</a> </a>
<% end %> <% end %>
@ -105,7 +104,7 @@
<div class="pure-u-1 pure-u-lg-3-5"></div> <div class="pure-u-1 pure-u-lg-3-5"></div>
<div class="pure-u-1 pure-u-lg-1-5" style="text-align:right"> <div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
<% if count == 60 %> <% if count == 60 %>
<a href="/channel/<%= channel.ucid %>?page=<%= page + 1 %><% if sort_by != "newest" %>&sort_by=<%= HTML.escape(sort_by) %><% end %>"> <a href="/channel/<%= ucid %>?page=<%= page + 1 %><% if sort_by != "newest" %>&sort_by=<%= HTML.escape(sort_by) %><% end %>">
<%= translate(locale, "Next page") %> <%= translate(locale, "Next page") %>
</a> </a>
<% end %> <% end %>

View file

@ -1,5 +1,8 @@
<% ucid = channel.ucid %>
<% author = HTML.escape(channel.author) %>
<% content_for "header" do %> <% content_for "header" do %>
<title><%= channel.author %> - Invidious</title> <title><%= author %> - Invidious</title>
<% end %> <% end %>
<% if channel.banner %> <% if channel.banner %>
@ -16,7 +19,7 @@
<div class="pure-u-2-3"> <div class="pure-u-2-3">
<div class="channel-profile"> <div class="channel-profile">
<img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>"> <img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>">
<span><%= channel.author %></span> <span><%= author %></span>
</div> </div>
</div> </div>
<div class="pure-u-1-3" style="text-align:right"> <div class="pure-u-1-3" style="text-align:right">
@ -33,8 +36,6 @@
</div> </div>
<div class="h-box"> <div class="h-box">
<% ucid = channel.ucid %>
<% author = channel.author %>
<% sub_count_text = number_to_short_text(channel.sub_count) %> <% sub_count_text = number_to_short_text(channel.sub_count) %>
<%= rendered "components/subscribe_widget" %> <%= rendered "components/subscribe_widget" %>
</div> </div>
@ -79,7 +80,7 @@
<script id="community_data" type="application/json"> <script id="community_data" type="application/json">
<%= <%=
{ {
"ucid" => channel.ucid, "ucid" => ucid,
"youtube_comments_text" => HTML.escape(translate(locale, "View YouTube comments")), "youtube_comments_text" => HTML.escape(translate(locale, "View YouTube comments")),
"comments_text" => HTML.escape(translate(locale, "View `x` comments", "{commentCount}")), "comments_text" => HTML.escape(translate(locale, "View `x` comments", "{commentCount}")),
"hide_replies_text" => HTML.escape(translate(locale, "Hide replies")), "hide_replies_text" => HTML.escape(translate(locale, "Hide replies")),

View file

@ -30,7 +30,7 @@
<p dir="auto"><%= HTML.escape(item.title) %></p> <p dir="auto"><%= HTML.escape(item.title) %></p>
</a> </a>
<a href="/channel/<%= item.ucid %>"> <a href="/channel/<%= item.ucid %>">
<p dir=auto"><b><%= HTML.escape(item.author) %></b></p> <p dir="auto"><b><%= HTML.escape(item.author) %></b></p>
</a> </a>
<% when MixVideo %> <% when MixVideo %>
<a href="/watch?v=<%= item.id %>&list=<%= item.rdid %>"> <a href="/watch?v=<%= item.id %>&list=<%= item.rdid %>">
@ -45,7 +45,7 @@
<p dir="auto"><%= HTML.escape(item.title) %></p> <p dir="auto"><%= HTML.escape(item.title) %></p>
</a> </a>
<a href="/channel/<%= item.ucid %>"> <a href="/channel/<%= item.ucid %>">
<p dir=auto"><b><%= HTML.escape(item.author) %></b></p> <p dir="auto"><b><%= HTML.escape(item.author) %></b></p>
</a> </a>
<% when PlaylistVideo %> <% when PlaylistVideo %>
<a style="width:100%" href="/watch?v=<%= item.id %>&list=<%= item.plid %>"> <a style="width:100%" href="/watch?v=<%= item.id %>&list=<%= item.plid %>">
@ -77,7 +77,7 @@
<div class="video-card-row flexible"> <div class="video-card-row flexible">
<div class="flex-left"><a href="/channel/<%= item.ucid %>"> <div class="flex-left"><a href="/channel/<%= item.ucid %>">
<p class="channel-name" dir=auto"><%= HTML.escape(item.author) %></p> <p class="channel-name" dir="auto"><%= HTML.escape(item.author) %></p>
</a></div> </a></div>
</div> </div>
@ -139,7 +139,7 @@
<div class="video-card-row flexible"> <div class="video-card-row flexible">
<div class="flex-left"><a href="/channel/<%= item.ucid %>"> <div class="flex-left"><a href="/channel/<%= item.ucid %>">
<p class="channel-name" dir=auto"><%= HTML.escape(item.author) %></p> <p class="channel-name" dir="auto"><%= HTML.escape(item.author) %></p>
</a></div> </a></div>
<div class="flex-right"> <div class="flex-right">
<div class="icon-buttons"> <div class="icon-buttons">

View file

@ -10,17 +10,22 @@
<% audio_streams.each_with_index do |fmt, i| %> <% audio_streams.each_with_index do |fmt, i| %>
<source src="/latest_version?id=<%= video.id %>&itag=<%= fmt["itag"] %><% if params.local %>&local=true<% end %>" type='<%= fmt["mimeType"] %>' label="<%= fmt["bitrate"] %>k" selected="<%= i == 0 ? true : false %>"> <source src="/latest_version?id=<%= video.id %>&itag=<%= fmt["itag"] %><% if params.local %>&local=true<% end %>" type='<%= fmt["mimeType"] %>' label="<%= fmt["bitrate"] %>k" selected="<%= i == 0 ? true : false %>">
<% end %> <% end %>
<% else %> <% else %>
<% if params.quality == "dash" %> <% if params.quality == "dash" %>
<source src="/api/manifest/dash/id/<%= video.id %>?local=true&unique_res=1" type='application/dash+xml' label="dash"> <source src="/api/manifest/dash/id/<%= video.id %>?local=true&unique_res=1" type='application/dash+xml' label="dash">
<% end %> <% end %>
<% fmt_stream.each_with_index do |fmt, i| %> <%
<% if params.quality %> fmt_stream.each_with_index do |fmt, i|
<source src="/latest_version?id=<%= video.id %>&itag=<%= fmt["itag"] %><% if params.local %>&local=true<% end %>" type='<%= fmt["mimeType"] %>' label="<%= fmt["quality"] %>" selected="<%= params.quality == fmt["quality"] %>"> src_url = "/latest_version?id=#{video.id}&itag=#{fmt["itag"]}"
<% else %> src_url += "&local=true" if params.local
<source src="/latest_version?id=<%= video.id %>&itag=<%= fmt["itag"] %><% if params.local %>&local=true<% end %>" type='<%= fmt["mimeType"] %>' label="<%= fmt["quality"] %>" selected="<%= i == 0 ? true : false %>">
<% end %> quality = fmt["quality"]
mimetype = fmt["mimeType"]
selected = params.quality ? (params.quality == quality) : (i == 0)
%>
<source src="<%= src_url %>" type="<%= mimetype %>" label="<%= quality %>" selected="<%= selected %>">
<% end %> <% end %>
<% end %> <% end %>

View file

@ -1,14 +1,16 @@
<% title = HTML.escape(playlist.title) %>
<% content_for "header" do %> <% content_for "header" do %>
<title><%= playlist.title %> - Invidious</title> <title><%= title %> - Invidious</title>
<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/playlist/<%= plid %>" /> <link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/playlist/<%= plid %>" />
<% end %> <% end %>
<form class="pure-form" action="/edit_playlist?list=<%= plid %>" method="post"> <form class="pure-form" action="/edit_playlist?list=<%= plid %>" method="post">
<div class="pure-g h-box"> <div class="pure-g h-box">
<div class="pure-u-2-3"> <div class="pure-u-2-3">
<h3><input class="pure-input-1" maxlength="150" name="title" type="text" value="<%= playlist.title %>"></h3> <h3><input class="pure-input-1" maxlength="150" name="title" type="text" value="<%= title %>"></h3>
<b> <b>
<%= playlist.author %> | <%= HTML.escape(playlist.author) %> |
<%= translate(locale, "`x` videos", "#{playlist.video_count}") %> | <%= translate(locale, "`x` videos", "#{playlist.video_count}") %> |
<%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> | <%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> |
<i class="icon <%= {"ion-md-globe", "ion-ios-unlock", "ion-ios-lock"}[playlist.privacy.value] %>"></i> <i class="icon <%= {"ion-md-globe", "ion-ios-unlock", "ion-ios-lock"}[playlist.privacy.value] %>"></i>
@ -55,11 +57,9 @@
</div> </div>
<div class="pure-g"> <div class="pure-g">
<% videos.each_slice(4) do |slice| %> <% videos.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %> <% end %>
<% end %>
<% end %>
</div> </div>
<div class="pure-g h-box"> <div class="pure-g h-box">

View file

@ -6,13 +6,13 @@
<div class="pure-u-1-3"> <div class="pure-u-1-3">
<h3><%= translate(locale, "`x` videos", %(<span id="count">#{user.watched.size}</span>)) %></h3> <h3><%= translate(locale, "`x` videos", %(<span id="count">#{user.watched.size}</span>)) %></h3>
</div> </div>
<div class="pure-u-1-3" style="text-align:center"> <div class="pure-u-1-3">
<h3> <h3 style="text-align:center">
<a href="/feed/subscriptions"><%= translate(locale, "`x` subscriptions", %(<span id="count">#{user.subscriptions.size}</span>)) %></a> <a href="/feed/subscriptions"><%= translate(locale, "`x` subscriptions", %(<span id="count">#{user.subscriptions.size}</span>)) %></a>
</h3> </h3>
</div> </div>
<div class="pure-u-1-3" style="text-align:right"> <div class="pure-u-1-3">
<h3> <h3 style="text-align:right">
<a href="/clear_watch_history"><%= translate(locale, "Clear watch history") %></a> <a href="/clear_watch_history"><%= translate(locale, "Clear watch history") %></a>
</h3> </h3>
</div> </div>
@ -28,31 +28,27 @@
<script src="/js/watched_widget.js"></script> <script src="/js/watched_widget.js"></script>
<div class="pure-g"> <div class="pure-g">
<% watched.each_slice(4) do |slice| %> <% watched.each do |item| %>
<% slice.each do |item| %> <div class="pure-u-1 pure-u-md-1-4">
<div class="pure-u-1 pure-u-md-1-4"> <div class="h-box">
<div class="h-box"> <a style="width:100%" href="/watch?v=<%= item %>">
<a style="width:100%" href="/watch?v=<%= item %>"> <% if !env.get("preferences").as(Preferences).thin_mode %>
<% if !env.get("preferences").as(Preferences).thin_mode %> <div class="thumbnail">
<div class="thumbnail"> <img class="thumbnail" src="/vi/<%= item %>/mqdefault.jpg"/>
<img class="thumbnail" src="/vi/<%= item %>/mqdefault.jpg"/> <form data-onsubmit="return_false" action="/watch_ajax?action_mark_unwatched=1&id=<%= item %>&referer=<%= env.get("current_page") %>" method="post">
<form data-onsubmit="return_false" action="/watch_ajax?action_mark_unwatched=1&id=<%= item %>&referer=<%= env.get("current_page") %>" method="post"> <input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>"> <p class="watched">
<p class="watched"> <a data-onclick="mark_unwatched" data-id="<%= item %>" href="javascript:void(0)">
<a data-onclick="mark_unwatched" data-id="<%= item %>" href="javascript:void(0)"> <button type="submit" style="all:unset"><i class="icon ion-md-trash"></i></button>
<button type="submit" style="all:unset"> </a>
<i class="icon ion-md-trash"></i> </p>
</button> </form>
</a> </div>
</p> <p></p>
</form> <% end %>
</div> </a>
<p></p> </div>
<% end %> </div>
</a>
</div>
</div>
<% end %>
<% end %> <% end %>
</div> </div>

View file

@ -26,7 +26,7 @@
<form class="pure-form pure-form-stacked" action="/login?referer=<%= URI.encode_www_form(referer) %>&type=google" method="post"> <form class="pure-form pure-form-stacked" action="/login?referer=<%= URI.encode_www_form(referer) %>&type=google" method="post">
<fieldset> <fieldset>
<% if email %> <% if email %>
<input name="email" type="hidden" value="<%= email %>"> <input name="email" type="hidden" value="<%= HTML.escape(email) %>">
<% else %> <% else %>
<label for="email"><%= translate(locale, "E-mail") %> :</label> <label for="email"><%= translate(locale, "E-mail") %> :</label>
<input required class="pure-input-1" name="email" type="email" placeholder="<%= translate(locale, "E-mail") %>"> <input required class="pure-input-1" name="email" type="email" placeholder="<%= translate(locale, "E-mail") %>">
@ -62,7 +62,7 @@
<form class="pure-form pure-form-stacked" action="/login?referer=<%= URI.encode_www_form(referer) %>&type=invidious" method="post"> <form class="pure-form pure-form-stacked" action="/login?referer=<%= URI.encode_www_form(referer) %>&type=invidious" method="post">
<fieldset> <fieldset>
<% if email %> <% if email %>
<input name="email" type="hidden" value="<%= email %>"> <input name="email" type="hidden" value="<%= HTML.escape(email) %>">
<% else %> <% else %>
<label for="email"><%= translate(locale, "User ID") %> :</label> <label for="email"><%= translate(locale, "User ID") %> :</label>
<input required class="pure-input-1" name="email" type="text" placeholder="<%= translate(locale, "User ID") %>"> <input required class="pure-input-1" name="email" type="text" placeholder="<%= translate(locale, "User ID") %>">

View file

@ -1,22 +1,20 @@
<% content_for "header" do %> <% content_for "header" do %>
<title><%= mix.title %> - Invidious</title> <title><%= HTML.escape(mix.title) %> - Invidious</title>
<% end %> <% end %>
<div class="pure-g h-box"> <div class="pure-g h-box">
<div class="pure-u-2-3"> <div class="pure-u-2-3">
<h3><%= mix.title %></h3> <h3><%= HTML.escape(mix.title) %></h3>
</div> </div>
<div class="pure-u-1-3" style="text-align:right"> <div class="pure-u-1-3">
<h3> <h3 style="text-align:right">
<a href="/feed/playlist/<%= mix.id %>"><i class="icon ion-logo-rss"></i></a> <a href="/feed/playlist/<%= mix.id %>"><i class="icon ion-logo-rss"></i></a>
</h3> </h3>
</div> </div>
</div> </div>
<div class="pure-g"> <div class="pure-g">
<% mix.videos.each_slice(4) do |slice| %> <% mix.videos.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %> <% end %>
<% end %>
<% end %>
</div> </div>

View file

@ -1,17 +1,20 @@
<% title = HTML.escape(playlist.title) %>
<% author = HTML.escape(playlist.author) %>
<% content_for "header" do %> <% content_for "header" do %>
<title><%= playlist.title %> - Invidious</title> <title><%= title %> - Invidious</title>
<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/playlist/<%= plid %>" /> <link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/playlist/<%= plid %>" />
<% end %> <% end %>
<div class="pure-g h-box"> <div class="pure-g h-box">
<div class="pure-u-2-3"> <div class="pure-u-2-3">
<h3><%= playlist.title %></h3> <h3><%= title %></h3>
<% if playlist.is_a? InvidiousPlaylist %> <% if playlist.is_a? InvidiousPlaylist %>
<b> <b>
<% if playlist.author == user.try &.email %> <% if playlist.author == user.try &.email %>
<a href="/view_all_playlists"><%= playlist.author %></a> | <a href="/view_all_playlists"><%= author %></a> |
<% else %> <% else %>
<%= playlist.author %> | <%= author %> |
<% end %> <% end %>
<%= translate(locale, "`x` videos", "#{playlist.video_count}") %> | <%= translate(locale, "`x` videos", "#{playlist.video_count}") %> |
<%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> | <%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> |
@ -26,11 +29,12 @@
</b> </b>
<% else %> <% else %>
<b> <b>
<a href="/channel/<%= playlist.ucid %>"><%= playlist.author %></a> | <a href="/channel/<%= playlist.ucid %>"><%= author %></a> |
<%= translate(locale, "`x` videos", "#{playlist.video_count}") %> | <%= translate(locale, "`x` videos", "#{playlist.video_count}") %> |
<%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> <%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %>
</b> </b>
<% end %> <% end %>
<% if !playlist.is_a? InvidiousPlaylist %> <% if !playlist.is_a? InvidiousPlaylist %>
<div class="pure-u-2-3"> <div class="pure-u-2-3">
<a href="https://www.youtube.com/playlist?list=<%= playlist.id %>"> <a href="https://www.youtube.com/playlist?list=<%= playlist.id %>">
@ -40,7 +44,6 @@
<a href="/redirect?referer=<%= env.get?("current_page") %>"> <a href="/redirect?referer=<%= env.get?("current_page") %>">
<%= translate(locale, "Switch Invidious Instance") %> <%= translate(locale, "Switch Invidious Instance") %>
</a> </a>
</div> </div>
<% end %> <% end %>
</div> </div>
@ -93,11 +96,9 @@
<% end %> <% end %>
<div class="pure-g"> <div class="pure-g">
<% videos.each_slice(4) do |slice| %> <% videos.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %> <% end %>
<% end %>
<% end %>
</div> </div>
<div class="pure-g h-box"> <div class="pure-g h-box">

View file

@ -1,5 +1,8 @@
<% ucid = channel.ucid %>
<% author = HTML.escape(channel.author) %>
<% content_for "header" do %> <% content_for "header" do %>
<title><%= channel.author %> - Invidious</title> <title><%= author %> - Invidious</title>
<% end %> <% end %>
<% if channel.banner %> <% if channel.banner %>
@ -16,12 +19,12 @@
<div class="pure-u-2-3"> <div class="pure-u-2-3">
<div class="channel-profile"> <div class="channel-profile">
<img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>"> <img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>">
<span><%= channel.author %></span> <span><%= author %></span>
</div> </div>
</div> </div>
<div class="pure-u-1-3" style="text-align:right"> <div class="pure-u-1-3" style="text-align:right">
<h3 style="text-align:right"> <h3 style="text-align:right">
<a href="/feed/channel/<%= channel.ucid %>"><i class="icon ion-logo-rss"></i></a> <a href="/feed/channel/<%= ucid %>"><i class="icon ion-logo-rss"></i></a>
</h3> </h3>
</div> </div>
</div> </div>
@ -33,8 +36,6 @@
</div> </div>
<div class="h-box"> <div class="h-box">
<% ucid = channel.ucid %>
<% author = channel.author %>
<% sub_count_text = number_to_short_text(channel.sub_count) %> <% sub_count_text = number_to_short_text(channel.sub_count) %>
<%= rendered "components/subscribe_widget" %> <%= rendered "components/subscribe_widget" %>
</div> </div>
@ -42,7 +43,7 @@
<div class="pure-g h-box"> <div class="pure-g h-box">
<div class="pure-g pure-u-1-3"> <div class="pure-g pure-u-1-3">
<div class="pure-u-1 pure-md-1-3"> <div class="pure-u-1 pure-md-1-3">
<a href="https://www.youtube.com/channel/<%= channel.ucid %>/playlists"><%= translate(locale, "View channel on YouTube") %></a> <a href="https://www.youtube.com/channel/<%= ucid %>/playlists"><%= translate(locale, "View channel on YouTube") %></a>
</div> </div>
<div class="pure-u-1 pure-md-1-3"> <div class="pure-u-1 pure-md-1-3">
@ -50,7 +51,7 @@
</div> </div>
<div class="pure-u-1 pure-md-1-3"> <div class="pure-u-1 pure-md-1-3">
<a href="/channel/<%= channel.ucid %>"><%= translate(locale, "Videos") %></a> <a href="/channel/<%= ucid %>"><%= translate(locale, "Videos") %></a>
</div> </div>
<div class="pure-u-1 pure-md-1-3"> <div class="pure-u-1 pure-md-1-3">
<% if !channel.auto_generated %> <% if !channel.auto_generated %>
@ -59,7 +60,7 @@
</div> </div>
<div class="pure-u-1 pure-md-1-3"> <div class="pure-u-1 pure-md-1-3">
<% if channel.tabs.includes? "community" %> <% if channel.tabs.includes? "community" %>
<a href="/channel/<%= channel.ucid %>/community"><%= translate(locale, "Community") %></a> <a href="/channel/<%= ucid %>/community"><%= translate(locale, "Community") %></a>
<% end %> <% end %>
</div> </div>
</div> </div>
@ -71,7 +72,7 @@
<% if sort_by == sort %> <% if sort_by == sort %>
<b><%= translate(locale, sort) %></b> <b><%= translate(locale, sort) %></b>
<% else %> <% else %>
<a href="/channel/<%= channel.ucid %>/playlists?sort_by=<%= sort %>"> <a href="/channel/<%= ucid %>/playlists?sort_by=<%= sort %>">
<%= translate(locale, sort) %> <%= translate(locale, sort) %>
</a> </a>
<% end %> <% end %>
@ -86,18 +87,16 @@
</div> </div>
<div class="pure-g"> <div class="pure-g">
<% items.each_slice(4) do |slice| %> <% items.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %> <% end %>
<% end %>
<% end %>
</div> </div>
<div class="pure-g h-box"> <div class="pure-g h-box">
<div class="pure-u-1 pure-u-md-4-5"></div> <div class="pure-u-1 pure-u-md-4-5"></div>
<div class="pure-u-1 pure-u-lg-1-5" style="text-align:right"> <div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
<% if continuation %> <% if continuation %>
<a href="/channel/<%= channel.ucid %>/playlists?continuation=<%= continuation %><% if sort_by != "last" %>&sort_by=<%= HTML.escape(sort_by) %><% end %>"> <a href="/channel/<%= ucid %>/playlists?continuation=<%= continuation %><% if sort_by != "last" %>&sort_by=<%= HTML.escape(sort_by) %><% end %>">
<%= translate(locale, "Next page") %> <%= translate(locale, "Next page") %>
</a> </a>
<% end %> <% end %>

View file

@ -12,9 +12,7 @@
<%= rendered "components/feed_menu" %> <%= rendered "components/feed_menu" %>
<div class="pure-g"> <div class="pure-g">
<% popular_videos.each_slice(4) do |slice| %> <% popular_videos.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %> <% end %>
<% end %>
<% end %>
</div> </div>

View file

@ -2,6 +2,8 @@
<title><%= search_query.not_nil!.size > 30 ? HTML.escape(query.not_nil![0,30].rstrip(".") + "...") : HTML.escape(query.not_nil!) %> - Invidious</title> <title><%= search_query.not_nil!.size > 30 ? HTML.escape(query.not_nil![0,30].rstrip(".") + "...") : HTML.escape(query.not_nil!) %> - Invidious</title>
<% end %> <% end %>
<% search_query_encoded = env.get?("search").try { |x| URI.encode(x.as(String), space_to_plus: true) } %>
<!-- Search redirection and filtering UI --> <!-- Search redirection and filtering UI -->
<% if count == 0 %> <% if count == 0 %>
<h3 style="text-align: center"> <h3 style="text-align: center">
@ -105,7 +107,7 @@
<div class="pure-g h-box v-box"> <div class="pure-g h-box v-box">
<div class="pure-u-1 pure-u-lg-1-5"> <div class="pure-u-1 pure-u-lg-1-5">
<% if page > 1 %> <% if page > 1 %>
<a href="/search?q=<%= HTML.escape(query.not_nil!) %>&page=<%= page - 1 %>"> <a href="/search?q=<%= search_query_encoded %>&page=<%= page - 1 %>">
<%= translate(locale, "Previous page") %> <%= translate(locale, "Previous page") %>
</a> </a>
<% end %> <% end %>
@ -113,7 +115,7 @@
<div class="pure-u-1 pure-u-lg-3-5"></div> <div class="pure-u-1 pure-u-lg-3-5"></div>
<div class="pure-u-1 pure-u-lg-1-5" style="text-align:right"> <div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
<% if count >= 20 %> <% if count >= 20 %>
<a href="/search?q=<%= HTML.escape(query.not_nil!) %>&page=<%= page + 1 %>"> <a href="/search?q=<%= search_query_encoded %>&page=<%= page + 1 %>">
<%= translate(locale, "Next page") %> <%= translate(locale, "Next page") %>
</a> </a>
<% end %> <% end %>
@ -121,17 +123,15 @@
</div> </div>
<div class="pure-g"> <div class="pure-g">
<% videos.each_slice(4) do |slice| %> <% videos.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %>
<% end %>
<% end %> <% end %>
</div> </div>
<div class="pure-g h-box"> <div class="pure-g h-box">
<div class="pure-u-1 pure-u-lg-1-5"> <div class="pure-u-1 pure-u-lg-1-5">
<% if page > 1 %> <% if page > 1 %>
<a href="/search?q=<%= HTML.escape(query.not_nil!) %>&page=<%= page - 1 %>"> <a href="/search?q=<%= search_query_encoded %>&page=<%= page - 1 %>">
<%= translate(locale, "Previous page") %> <%= translate(locale, "Previous page") %>
</a> </a>
<% end %> <% end %>
@ -139,7 +139,7 @@
<div class="pure-u-1 pure-u-lg-3-5"></div> <div class="pure-u-1 pure-u-lg-3-5"></div>
<div class="pure-u-1 pure-u-lg-1-5" style="text-align:right"> <div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
<% if count >= 20 %> <% if count >= 20 %>
<a href="/search?q=<%= HTML.escape(query.not_nil!) %>&page=<%= page + 1 %>"> <a href="/search?q=<%= search_query_encoded %>&page=<%= page + 1 %>">
<%= translate(locale, "Next page") %> <%= translate(locale, "Next page") %>
</a> </a>
<% end %> <% end %>

View file

@ -10,15 +10,15 @@
</a> </a>
</h3> </h3>
</div> </div>
<div class="pure-u-1-3" style="text-align:center"> <div class="pure-u-1-3">
<h3> <h3 style="text-align:center">
<a href="/feed/history"> <a href="/feed/history">
<%= translate(locale, "Watch history") %> <%= translate(locale, "Watch history") %>
</a> </a>
</h3> </h3>
</div> </div>
<div class="pure-u-1-3" style="text-align:right"> <div class="pure-u-1-3">
<h3> <h3 style="text-align:right">
<a href="/data_control?referer=<%= URI.encode_www_form(referer) %>"> <a href="/data_control?referer=<%= URI.encode_www_form(referer) %>">
<%= translate(locale, "Import/export") %> <%= translate(locale, "Import/export") %>
</a> </a>
@ -31,7 +31,7 @@
<div class="pure-g<% if channel.deleted %> deleted <% end %>"> <div class="pure-g<% if channel.deleted %> deleted <% end %>">
<div class="pure-u-2-5"> <div class="pure-u-2-5">
<h3 style="padding-left:0.5em"> <h3 style="padding-left:0.5em">
<a href="/channel/<%= channel.id %>"><%= channel.author %></a> <a href="/channel/<%= channel.id %>"><%= HTML.escape(channel.author) %></a>
</h3> </h3>
</div> </div>
<div class="pure-u-2-5"></div> <div class="pure-u-2-5"></div>

View file

@ -11,13 +11,13 @@
<a href="/subscription_manager"><%= translate(locale, "Manage subscriptions") %></a> <a href="/subscription_manager"><%= translate(locale, "Manage subscriptions") %></a>
</h3> </h3>
</div> </div>
<div class="pure-u-1-3" style="text-align:center"> <div class="pure-u-1-3">
<h3> <h3 style="text-align:center">
<a href="/feed/history"><%= translate(locale, "Watch history") %></a> <a href="/feed/history"><%= translate(locale, "Watch history") %></a>
</h3> </h3>
</div> </div>
<div class="pure-u-1-3" style="text-align:right"> <div class="pure-u-1-3">
<h3> <h3 style="text-align:right">
<a href="/feed/private?token=<%= token %>"><i class="icon ion-logo-rss"></i></a> <a href="/feed/private?token=<%= token %>"><i class="icon ion-logo-rss"></i></a>
</h3> </h3>
</div> </div>
@ -34,11 +34,9 @@
<% end %> <% end %>
<div class="pure-g"> <div class="pure-g">
<% notifications.each_slice(4) do |slice| %> <% notifications.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %> <% end %>
<% end %>
<% end %>
</div> </div>
<div class="h-box"> <div class="h-box">
@ -55,11 +53,9 @@
<script src="/js/watched_widget.js"></script> <script src="/js/watched_widget.js"></script>
<div class="pure-g"> <div class="pure-g">
<% videos.each_slice(4) do |slice| %> <% videos.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %> <% end %>
<% end %>
<% end %>
</div> </div>
<div class="pure-g h-box"> <div class="pure-g h-box">

View file

@ -41,9 +41,7 @@
</div> </div>
<div class="pure-g"> <div class="pure-g">
<% trending.each_slice(4) do |slice| %> <% trending.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %> <% end %>
<% end %>
<% end %>
</div> </div>

View file

@ -16,11 +16,9 @@
</div> </div>
<div class="pure-g"> <div class="pure-g">
<% items_created.each_slice(4) do |slice| %> <% items_created.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %> <% end %>
<% end %>
<% end %>
</div> </div>
<div class="pure-g h-box"> <div class="pure-g h-box">
@ -30,9 +28,7 @@
</div> </div>
<div class="pure-g"> <div class="pure-g">
<% items_saved.each_slice(4) do |slice| %> <% items_saved.each do |item| %>
<% slice.each do |item| %> <%= rendered "components/item" %>
<%= rendered "components/item" %> <% end %>
<% end %>
<% end %>
</div> </div>

View file

@ -1,10 +1,15 @@
<% ucid = video.ucid %>
<% title = HTML.escape(video.title) %>
<% author = HTML.escape(video.author) %>
<% content_for "header" do %> <% content_for "header" do %>
<meta name="thumbnail" content="<%= thumbnail %>"> <meta name="thumbnail" content="<%= thumbnail %>">
<meta name="description" content="<%= HTML.escape(video.short_description) %>"> <meta name="description" content="<%= HTML.escape(video.short_description) %>">
<meta name="keywords" content="<%= video.keywords.join(",") %>"> <meta name="keywords" content="<%= video.keywords.join(",") %>">
<meta property="og:site_name" content="Invidious"> <meta property="og:site_name" content="Invidious">
<meta property="og:url" content="<%= HOST_URL %>/watch?v=<%= video.id %>"> <meta property="og:url" content="<%= HOST_URL %>/watch?v=<%= video.id %>">
<meta property="og:title" content="<%= HTML.escape(video.title) %>"> <meta property="og:title" content="<%= title %>">
<meta property="og:image" content="/vi/<%= video.id %>/maxres.jpg"> <meta property="og:image" content="/vi/<%= video.id %>/maxres.jpg">
<meta property="og:description" content="<%= video.short_description %>"> <meta property="og:description" content="<%= video.short_description %>">
<meta property="og:type" content="video.other"> <meta property="og:type" content="video.other">
@ -16,7 +21,7 @@
<meta name="twitter:card" content="player"> <meta name="twitter:card" content="player">
<meta name="twitter:site" content="@omarroth1"> <meta name="twitter:site" content="@omarroth1">
<meta name="twitter:url" content="<%= HOST_URL %>/watch?v=<%= video.id %>"> <meta name="twitter:url" content="<%= HOST_URL %>/watch?v=<%= video.id %>">
<meta name="twitter:title" content="<%= HTML.escape(video.title) %>"> <meta name="twitter:title" content="<%= title %>">
<meta name="twitter:description" content="<%= video.short_description %>"> <meta name="twitter:description" content="<%= video.short_description %>">
<meta name="twitter:image" content="<%= HOST_URL %>/vi/<%= video.id %>/maxres.jpg"> <meta name="twitter:image" content="<%= HOST_URL %>/vi/<%= video.id %>/maxres.jpg">
<meta name="twitter:player" content="<%= HOST_URL %>/embed/<%= video.id %>"> <meta name="twitter:player" content="<%= HOST_URL %>/embed/<%= video.id %>">
@ -24,7 +29,7 @@
<meta name="twitter:player:height" content="720"> <meta name="twitter:player:height" content="720">
<link rel="alternate" href="https://www.youtube.com/watch?v=<%= video.id %>"> <link rel="alternate" href="https://www.youtube.com/watch?v=<%= video.id %>">
<%= rendered "components/player_sources" %> <%= rendered "components/player_sources" %>
<title><%= HTML.escape(video.title) %> - Invidious</title> <title><%= title %> - Invidious</title>
<!-- Description expansion also updates the 'Show more' button to 'Show less' so <!-- Description expansion also updates the 'Show more' button to 'Show less' so
we're going to need to do it here in order to allow for translations. we're going to need to do it here in order to allow for translations.
@ -69,7 +74,7 @@ we're going to need to do it here in order to allow for translations.
<div class="h-box"> <div class="h-box">
<h1> <h1>
<%= HTML.escape(video.title) %> <%= title %>
<% if params.listen %> <% if params.listen %>
<a title="<%=translate(locale, "Video mode")%>" href="/watch?<%= env.params.query %>&listen=0"> <a title="<%=translate(locale, "Video mode")%>" href="/watch?<%= env.params.query %>&listen=0">
<i class="icon ion-ios-videocam"></i> <i class="icon ion-ios-videocam"></i>
@ -134,8 +139,8 @@ we're going to need to do it here in order to allow for translations.
<div class="pure-control-group"> <div class="pure-control-group">
<label for="playlist_id"><%= translate(locale, "Add to playlist: ") %></label> <label for="playlist_id"><%= translate(locale, "Add to playlist: ") %></label>
<select style="width:100%" name="playlist_id" id="playlist_id"> <select style="width:100%" name="playlist_id" id="playlist_id">
<% playlists.each do |plid, title| %> <% playlists.each do |plid, playlist_title| %>
<option data-plid="<%= plid %>" value="<%= plid %>"><%= title %></option> <option data-plid="<%= plid %>" value="<%= plid %>"><%= HTML.escape(playlist_title) %></option>
<% end %> <% end %>
</select> </select>
</div> </div>
@ -227,12 +232,10 @@ we're going to need to do it here in order to allow for translations.
<% if !video.author_thumbnail.empty? %> <% if !video.author_thumbnail.empty? %>
<img src="/ggpht<%= URI.parse(video.author_thumbnail).request_target %>"> <img src="/ggpht<%= URI.parse(video.author_thumbnail).request_target %>">
<% end %> <% end %>
<span id="channel-name"><%= video.author %></span> <span id="channel-name"><%= author %></span>
</div> </div>
</a> </a>
<% ucid = video.ucid %>
<% author = video.author %>
<% sub_count_text = video.sub_count_text %> <% sub_count_text = video.sub_count_text %>
<%= rendered "components/subscribe_widget" %> <%= rendered "components/subscribe_widget" %>