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)
このコミットが含まれているのは:
Samantaz Fox 2021-07-15 23:01:36 +02:00 committed by GitHub
コミット 56ebef4352
この署名に対応する既知のキーがデータベースに存在しません
GPGキーID: 4AEE18F83AFDEB23
19個のファイルの変更161行の追加169行の削除

ファイルの表示

@ -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

ファイルの表示

@ -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>

ファイルの表示

@ -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 %>

ファイルの表示

@ -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")),

ファイルの表示

@ -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">

ファイルの表示

@ -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 %>

ファイルの表示

@ -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">

ファイルの表示

@ -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>

ファイルの表示

@ -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") %>">

ファイルの表示

@ -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>

ファイルの表示

@ -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">

ファイルの表示

@ -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 %>

ファイルの表示

@ -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>

ファイルの表示

@ -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 %>

ファイルの表示

@ -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>

ファイルの表示

@ -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">

ファイルの表示

@ -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>

ファイルの表示

@ -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>

ファイルの表示

@ -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" %>