视频标题的显示发生了变化。

This commit is contained in:
awer123456 2026-09-02 15:52:48 +08:00
parent b3a3f3a6df
commit f28ac7c7cb
3 changed files with 98 additions and 1 deletions

View File

@ -0,0 +1,56 @@
require "../../spec_helper"
require "../../../src/invidious/frontend/watch_page"
Spectator.describe Invidious::Frontend::WatchPage do
describe ".linkify_title_hashtags" do
it "links hashtags while preserving surrounding punctuation" do
result = Invidious::Frontend::WatchPage.linkify_title_hashtags(
"Watch (#music), then #news!"
)
expect(result).to eq(
%(Watch (<a href="/hashtag/music">#music</a>), then <a href="/hashtag/news">#news</a>!)
)
end
it "does not link hashes inside words or without a name" do
result = Invidious::Frontend::WatchPage.linkify_title_hashtags(
"C# test#music #"
)
expect(result).to eq("C# test#music #")
end
it "links and encodes Unicode hashtags" do
hashtag = "\u{97F3}\u{4E50}"
result = Invidious::Frontend::WatchPage.linkify_title_hashtags(
"Listen ##{hashtag}"
)
expect(result).to eq(
%(Listen <a href="/hashtag/%E9%9F%B3%E4%B9%90">##{hashtag}</a>)
)
end
it "escapes title markup and link text" do
result = Invidious::Frontend::WatchPage.linkify_title_hashtags(
%(<script>#music</script> & #news)
)
expect(result).to eq(
%(&lt;script&gt;<a href="/hashtag/music">#music</a>&lt;/script&gt; &amp; <a href="/hashtag/news">#news</a>)
)
end
it "does not turn character-reference-like text into hashtag links" do
result = Invidious::Frontend::WatchPage.linkify_title_hashtags(
"Literal &#65; and &#x41; plus #music"
)
expect(result).to eq(
%(Literal &amp;#65; and &amp;#x41; plus <a href="/hashtag/music">#music</a>)
)
end
end
end

View File

@ -1,6 +1,47 @@
module Invidious::Frontend::WatchPage
extend self
def linkify_title_hashtags(title : String) : String
characters = title.chars
String.build(title.bytesize) do |html|
index = 0
while index < characters.size
character = characters[index]
starts_hashtag = character == '#' &&
(index == 0 || !hashtag_prefix_character?(characters[index - 1]))
if starts_hashtag
hashtag_end = index + 1
while hashtag_end < characters.size && hashtag_character?(characters[hashtag_end])
hashtag_end += 1
end
if hashtag_end > index + 1
hashtag = characters[index + 1...hashtag_end].join
html << %(<a href="/hashtag/) << URI.encode_path(hashtag) << %(">#)
html << HTML.escape(hashtag) << "</a>"
index = hashtag_end
next
end
end
html << HTML.escape(character.to_s)
index += 1
end
end
end
private def hashtag_character?(character : Char) : Bool
character.alphanumeric? || character == '_'
end
private def hashtag_prefix_character?(character : Char) : Bool
hashtag_character?(character) || character == '&'
end
# A handy structure to pass many elements at
# once to the download widget function
struct VideoAssets

View File

@ -93,7 +93,7 @@ we're going to need to do it here in order to allow for translations.
<div class="h-box">
<h1>
<%= title %>
<%= Invidious::Frontend::WatchPage.linkify_title_hashtags(video.title) %>
<% if params.listen %>
<a title="<%=I18n.translate(locale, "Video mode")%>" id="link-iv-listen" data-base-url="/watch?<%= env.params.query %>&listen=0" href="/watch?<%= env.params.query %>&listen=0">
<i class="icon ion-ios-videocam"></i>