Module: Asciidoctor::BeautifyUri::Providers::Youtube

Defined in:
lib/asciidoctor/beautify_uri/providers/youtube.rb

Overview

uri::youtube:watch?v=[] — resolves live via YouTube's free, unauthenticated oEmbed endpoint. Per explicit decision: the HTML5 backend defers to Asciidoctor's own built-in video block macro (an embedded iframe player, poster=youtube) rather than a custom static card — see video_block below. PDF has no such built-in, so it gets the shared PdfCard static-card treatment like Spotify.

Constant Summary collapse

OEMBED_ENDPOINT =
'https://www.youtube.com/oembed'
HTTP_TIMEOUT =
8

Class Method Summary collapse

Class Method Details

.defer_html_to_video?Boolean

Returns:

  • (Boolean)


24
# File 'lib/asciidoctor/beautify_uri/providers/youtube.rb', line 24

def self.defer_html_to_video? = true

.display_nameObject



22
# File 'lib/asciidoctor/beautify_uri/providers/youtube.rb', line 22

def self.display_name = 'YouTube'

.extract_video_id(path) ⇒ Object



59
60
61
62
63
64
65
66
67
# File 'lib/asciidoctor/beautify_uri/providers/youtube.rb', line 59

def self.extract_video_id(path)
  if path.include?('?')
    _, query = path.split('?', 2)
    params = URI.decode_www_form(query).to_h
    params['v']
  else
    path
  end
end

.get_json(uri) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/asciidoctor/beautify_uri/providers/youtube.rb', line 69

def self.get_json(uri)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.open_timeout = HTTP_TIMEOUT
  http.read_timeout = HTTP_TIMEOUT
  response = http.request(Net::HTTP::Get.new(uri))
  return nil unless response.is_a?(Net::HTTPSuccess)

  JSON.parse(response.body)
rescue StandardError => e
  Logging.debug(%(youtube request to #{uri} failed: #{e.message}))
  nil
end

.icon_blockObject



26
27
28
# File 'lib/asciidoctor/beautify_uri/providers/youtube.rb', line 26

def self.icon_block
  %(<span class="uri-card-icon">#{CardRenderer.icon 'youtube'}</span>)
end

.keyObject



21
# File 'lib/asciidoctor/beautify_uri/providers/youtube.rb', line 21

def self.key = 'youtube'


23
# File 'lib/asciidoctor/beautify_uri/providers/youtube.rb', line 23

def self.link_text = 'Watch on YouTube'

.resolve(path, _doc) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/asciidoctor/beautify_uri/providers/youtube.rb', line 30

def self.resolve(path, _doc)
  return nil if path.nil? || path.empty?

  video_id = extract_video_id(path)
  return nil unless video_id

  canonical_url = "https://www.youtube.com/watch?v=#{video_id}"
  uri = URI(OEMBED_ENDPOINT)
  uri.query = URI.encode_www_form(url: canonical_url, format: 'json')
  json = get_json(uri)
  return nil unless json && json['title']

  {
    title: json['title'],
    subtitle: json['author_name'],
    thumbnail_url: json['thumbnail_url'],
    thumbnail_width: json['thumbnail_width'],
    thumbnail_height: json['thumbnail_height'],
    target_url: canonical_url,
    video_id: video_id,
  }
end

.video_block(parent, data) ⇒ Object



53
54
55
56
57
# File 'lib/asciidoctor/beautify_uri/providers/youtube.rb', line 53

def self.video_block(parent, data)
  ::Asciidoctor::Block.new(parent, :video,
    attributes: { 'target' => data[:video_id], 'poster' => 'youtube' },
    content_model: :empty)
end