Compare commits

...

2 commits

Author SHA1 Message Date
bbec111997
feat(experimental): minify js files using esbuild
All checks were successful
Invidious CI / build (push) Successful in 5m37s
2025-04-05 03:03:04 -03:00
e3d60a0517
fix missing scheme on meta elements
move scheme logic
2025-04-05 03:03:00 -03:00
20 changed files with 148 additions and 38 deletions

1
assets/js/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
minified

96
scripts/minify-js.cr Executable file
View file

@ -0,0 +1,96 @@
require "http"
require "colorize"
ESBUILD_VERSION = "0.25.0"
esbuild_os = ""
esbuild_arch = ""
# https://esbuild.github.io/getting-started/#other-ways-to-install
{% if flag?(:linux) %}
esbuild_os = "linux"
{% elsif flag?(:windows) %}
esbuild_os = "win32"
{% elsif flag?(:darwin) %}
esbuild_os = "darwin"
{% elsif flag?(:freebsd) %}
esbuild_os = "freebsd"
{% elsif flag?(:openbsd) %}
esbuild_os = "openbsd"
{% elsif flag?(:netbsd) %}
esbuild_os = "netbsd"
{% elsif flag?(:solaris) %}
esbuild_os = "sunos"
{% else %}
esbuild_os = "linux"
{% end %}
{% if flag?(:x86_64) %}
esbuild_arch = "x64"
{% elsif flag?(:arm64) %}
esbuild_arch = "arm64"
{% else %}
esbuild_arch = "x64"
{% end %}
tmp_dir_path = "#{Dir.tempdir}/invidious-esbuild-binary"
esbuild_tar_location = "#{tmp_dir_path}/esbuild-#{esbuild_os}-#{esbuild_os}-#{ESBUILD_VERSION}.tgz"
esbuild_binary_location = "#{tmp_dir_path}/package/bin/esbuild"
Dir.mkdir(tmp_dir_path) if !Dir.exists? tmp_dir_path
esbuild_url = "https://registry.npmjs.org/@esbuild/#{esbuild_os}-#{esbuild_arch}/-/#{esbuild_os}-#{esbuild_arch}-#{ESBUILD_VERSION}.tgz"
# Download esbuild binary
HTTP::Client.get(esbuild_url) do |response|
puts "Downloading esbuild from #{esbuild_url}"
data = response.body_io.gets_to_end
File.write(esbuild_tar_location, data)
`tar -vzxf '#{esbuild_tar_location}' -C '#{tmp_dir_path}'`
raise "Extraction for #{esbuild_tar_location} failed" if !$?.success?
puts "esbuild downloaded successfully"
end
files_to_minify = [
"_helpers.js",
"comments.js",
"embed.js",
"handlers.js",
"notifications.js",
"pagination.js",
"playlist_widget.js",
"post.js",
"sse.js",
"themes.js",
"watch.js",
"player.js",
"watched_indicator.js",
"watched_widget.js",
]
files_to_minify.each do |file|
file_path = "assets/js/#{file}"
outdir = "assets/js/minified"
process_output = IO::Memory.new
process = Process.run("#{esbuild_binary_location}", error: process_output, args: [
file_path,
"--color=false",
"--sourcemap",
"--minify",
"--outdir=#{outdir}",
]
)
if process.success?
puts "Minified #{file}".colorize(:green)
elsif !process.success?
puts "Failed to minify #{file}, esbuild exited with exit code #{process.exit_code}: #{process_output.to_s.split("\n").first}".colorize(:red)
raise Exception.new("All files have to be minified sucessfully in order to compile!")
end
end
puts "Minify done!"
# Cleanup
`rm -rf #{tmp_dir_path}`

View file

@ -160,6 +160,15 @@ LOGGER = Invidious::LogHandler.new(OUTPUT, CONFIG.log_level, CONFIG.colorize_log
# Check table integrity
Invidious::Database.check_integrity(CONFIG)
# Minifies Invidious Javascript
{% if flag?(:minify_debug) || (flag?(:release) || flag?(:production)) && !flag?(:skip_minified_js) %}
{% puts "\nMinifying Invidious JavaScript\n" %}
{% puts run("../scripts/minify-js.cr").stringify %}
JS_PATH="js/minified"
{% else %}
JS_PATH="js"
{% end %}
{% if !flag?(:skip_videojs_download) %}
# Resolve player dependencies. This is done at compile time.
#

View file

@ -67,9 +67,11 @@ module Invidious::Routes::BeforeAll
frame_ancestors = "'none'"
end
scheme = env.request.headers["X-Forwarded-Proto"]? || ("https" if CONFIG.https_only) || "http"
env.set "scheme", scheme
# TODO: Remove style-src's 'unsafe-inline', requires to remove all
# inline styles (<style> [..] </style>, style=" [..] ")
scheme = env.request.headers["X-Forwarded-Proto"]? || ("https" if CONFIG.https_only) || "http"
env.response.headers["Content-Security-Policy"] = {
"default-src 'none'",
"script-src 'self'",

View file

@ -29,7 +29,7 @@
}.to_pretty_json
%>
</script>
<script src="/js/playlist_widget.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/playlist_widget.js?v=<%= ASSET_COMMIT %>"></script>
<%= rendered "components/items_paginated" %>

View file

@ -3,6 +3,7 @@
author = HTML.escape(channel.author)
channel_profile_pic = URI.parse(channel.author_thumbnail).request_target
host = env.request.headers["Host"]
scheme = env.get("scheme")
relative_url =
case selected_tab
@ -32,19 +33,19 @@
<%- if selected_tab.videos? -%>
<meta name="description" content="<%= channel.description %>">
<meta property="og:site_name" content="Invidious">
<meta property="og:url" content="<%= host %>/channel/<%= ucid %>">
<meta property="og:url" content="<%= scheme %>://<%= host %>/channel/<%= ucid %>">
<meta property="og:title" content="<%= author %>">
<meta property="og:image" content="<%= host %>/ggpht<%= channel_profile_pic %>">
<meta property="og:image" content="<%= scheme %>://<%= host %>/ggpht<%= channel_profile_pic %>">
<meta property="og:description" content="<%= channel.description %>">
<meta name="twitter:card" content="summary">
<meta name="twitter:url" content="<%= host %>/channel/<%= ucid %>">
<meta name="twitter:url" content="<%= scheme %>://<%= host %>/channel/<%= ucid %>">
<meta name="twitter:title" content="<%= author %>">
<meta name="twitter:description" content="<%= channel.description %>">
<meta name="twitter:image" content="<%= host %>/ggpht<%= channel_profile_pic %>">
<meta name="twitter:image" content="<%= scheme %>://<%= host %>/ggpht<%= channel_profile_pic %>">
<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/channel/<%= ucid %>" />
<%- end -%>
<script src="/js/pagination.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/pagination.js?v=<%= ASSET_COMMIT %>"></script>
<link rel="alternate" href="<%= youtube_url %>">
<title><%= author %> - Invidious</title>

View file

@ -43,4 +43,4 @@
}.to_pretty_json
%>
</script>
<script src="/js/community.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/community.js?v=<%= ASSET_COMMIT %>"></script>

View file

@ -18,4 +18,4 @@
%>
</script>
<script src="/js/watched_indicator.js"></script>
<script src="/<%= JS_PATH %>/watched_indicator.js"></script>

View file

@ -86,4 +86,4 @@
}.to_pretty_json
%>
</script>
<script src="/js/player.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/player.js?v=<%= ASSET_COMMIT %>"></script>

View file

@ -27,7 +27,7 @@
}.to_pretty_json
%>
</script>
<script src="/js/subscribe_widget.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/subscribe_widget.js?v=<%= ASSET_COMMIT %>"></script>
<% else %>
<a id="subscribe" class="pure-button pure-button-primary"
href="/login?referer=<%= env.get("current_page") %>">

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="/css/default.css?v=<%= ASSET_COMMIT %>">
<link rel="stylesheet" href="/css/embed.css?v=<%= ASSET_COMMIT %>">
<title><%= HTML.escape(video.title) %> - Invidious</title>
<script src="/js/_helpers.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/_helpers.js?v=<%= ASSET_COMMIT %>"></script>
</head>
<body class="dark-theme">
@ -32,6 +32,6 @@
</script>
<%= rendered "components/player" %>
<script src="/js/embed.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/embed.js?v=<%= ASSET_COMMIT %>"></script>
</body>
</html>

View file

@ -25,7 +25,7 @@
}.to_pretty_json
%>
</script>
<script src="/js/watched_widget.js"></script>
<script src="/<%= JS_PATH %>/watched_widget.js"></script>
<div class="pure-g">
<% watched.each do |item| %>

View file

@ -40,4 +40,4 @@
<% end %>
</div>
<script src="/js/watched_indicator.js"></script>
<script src="/<%= JS_PATH %>/watched_indicator.js"></script>

View file

@ -17,4 +17,4 @@
<% end %>
</div>
<script src="/js/watched_indicator.js"></script>
<script src="/<%= JS_PATH %>/watched_indicator.js"></script>

View file

@ -53,7 +53,7 @@
}.to_pretty_json
%>
</script>
<script src="/js/watched_widget.js"></script>
<script src="/<%= JS_PATH %>/watched_widget.js"></script>
<div class="pure-g">
@ -62,7 +62,7 @@
<% end %>
</div>
<script src="/js/watched_indicator.js"></script>
<script src="/<%= JS_PATH %>/watched_indicator.js"></script>
<%=
IV::Frontend::Pagination.nav_numeric(locale,

View file

@ -46,4 +46,4 @@
<% end %>
</div>
<script src="/js/watched_indicator.js"></script>
<script src="/<%= JS_PATH %>/watched_indicator.js"></script>

View file

@ -118,7 +118,7 @@
}.to_pretty_json
%>
</script>
<script src="/js/playlist_widget.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/playlist_widget.js?v=<%= ASSET_COMMIT %>"></script>
<% end %>

View file

@ -44,5 +44,5 @@
}.to_pretty_json
%>
</script>
<script src="/js/comments.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/js/post.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/comments.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/post.js?v=<%= ASSET_COMMIT %>"></script>

View file

@ -22,7 +22,7 @@
<link rel="stylesheet" href="/css/ionicons.min.css?v=<%= ASSET_COMMIT %>">
<link rel="stylesheet" href="/css/default.css?v=<%= ASSET_COMMIT %>">
<link rel="stylesheet" href="/css/carousel.css?v=<%= ASSET_COMMIT %>">
<script src="/js/_helpers.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/_helpers.js?v=<%= ASSET_COMMIT %>"></script>
</head>
<body class="<%= dark_mode.blank? ? "no" : dark_mode %>-theme">
@ -110,6 +110,7 @@
if CONFIG.invidious_companion.present?
current_backend = env.get?("current_companion").try &.as(Int32)
domain = env.get?("domain").try &.as(Bool)
scheme = env.get("scheme")
status = BackendInfo.get_status
%>
<div class="h-box" style="margin-bottom: 10px;">
@ -117,7 +118,6 @@
<% if domain %>
<% CONFIG.invidious_companion.each_with_index do | companion, index | %>
<% is_current_backend_host = companion.domain == env.request.headers["Host"] %>
<% scheme = env.request.headers["X-Forwarded-Proto"]? || ("https" if CONFIG.https_only) || "http" %>
<a href="<%= scheme %>://<%= companion.domain %><%= env.request.resource %>" style="<%= is_current_backend_host ? "text-decoration-line: underline;" : "" %> display: inline-block;">
Backend<%= HTML.escape((index + 1).to_s) %> <%= HTML.escape(companion.note) %>
<span style="color:
@ -163,10 +163,10 @@
</div>
</div>
<script src="/js/handlers.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/js/themes.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/handlers.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/themes.js?v=<%= ASSET_COMMIT %>"></script>
<% if env.get? "user" %>
<script src="/js/sse.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/sse.js?v=<%= ASSET_COMMIT %>"></script>
<script id="notification_data" type="application/json">
<%=
{
@ -176,7 +176,7 @@
%>
</script>
<% if CONFIG.enable_user_notifications %>
<script src="/js/notifications.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/notifications.js?v=<%= ASSET_COMMIT %>"></script>
<% end %>
<% end %>

View file

@ -2,31 +2,32 @@
<% title = HTML.escape(video.title) %>
<% author = HTML.escape(video.author) %>
<% host = env.request.headers["Host"] %>
<% scheme = env.get("scheme") %>
<% content_for "header" do %>
<meta name="thumbnail" content="<%= thumbnail %>">
<meta name="thumbnail" content="<%= scheme %>://<%= host %><%= thumbnail %>">
<meta name="description" content="<%= HTML.escape(video.short_description) %>">
<meta name="keywords" content="<%= video.keywords.join(",") %>">
<meta property="og:site_name" content="<%= author %> | Invidious">
<meta property="og:url" content="<%= host %>/watch?v=<%= video.id %>">
<meta property="og:url" content="<%= scheme %>://<%= host %>/watch?v=<%= video.id %>">
<meta property="og:title" content="<%= title %>">
<meta property="og:image" content="<%= host %>/vi/<%= video.id %>/maxres.jpg">
<meta property="og:image" content="<%= scheme %>://<%= host %>/vi/<%= video.id %>/maxres.jpg">
<meta property="og:description" content="<%= HTML.escape(video.short_description) %>">
<meta property="og:type" content="video.other">
<!-- This shouldn't be empty, ever. -->
<meta property="og:video" content="<%= video_url %>">
<meta property="og:video" content="<%= video_url %>">
<meta property="og:video:url" content="<%= video_url %>">
<meta property="og:video:secure_url" content="<%= video_url %>">
<meta property="og:video:type" content="video/mp4">
<meta property="og:video:width" content="640">
<meta property="og:video:height" content="360">
<meta name="twitter:card" content="player">
<meta name="twitter:url" content="<%= host %>/watch?v=<%= video.id %>">
<meta name="twitter:url" content="<%= scheme %>://<%= host %>/watch?v=<%= video.id %>">
<meta name="twitter:title" content="<%= title %>">
<meta name="twitter:description" content="<%= HTML.escape(video.short_description) %>">
<meta name="twitter:image" content="<%= host %>/vi/<%= video.id %>/maxres.jpg">
<meta name="twitter:player" content="<%= host %>/embed/<%= video.id %>">
<meta name="twitter:image" content="<%= scheme %>://<%= host %>/vi/<%= video.id %>/maxres.jpg">
<meta name="twitter:player" content="<%= scheme %>://<%= host %>/embed/<%= video.id %>">
<meta name="twitter:player:width" content="1280">
<meta name="twitter:player:height" content="720">
<link rel="alternate" href="https://www.youtube.com/watch?v=<%= video.id %>">
@ -198,7 +199,7 @@ we're going to need to do it here in order to allow for translations.
}.to_pretty_json
%>
</script>
<script src="/js/playlist_widget.js?v=<%= Time.utc.to_unix_ms %>"></script>
<script src="/<%= JS_PATH %>/playlist_widget.js?v=<%= Time.utc.to_unix_ms %>"></script>
<% end %>
<% end %>
@ -390,5 +391,5 @@ we're going to need to do it here in order to allow for translations.
</div>
<% end %>
</div>
<script src="/js/comments.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/js/watch.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/comments.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/<%= JS_PATH %>/watch.js?v=<%= ASSET_COMMIT %>"></script>