Skip to content

Commit bbcb8c0

Browse files
authored
Docs: Add Sphinx directive for youtube embeds (#3394)
Add a simple directive `.. youtube`, implemented as a local sphinx extension, that takes one argument — either: - A YouTube video ID (e.g. `aqz-KE-bpKQ`) - A YouTube URL (e.g. `https://www.youtube.com/watch?v=aqz-KE-bpKQ`) In either case, when generating HTML docs the directive will be replaced with an HTML embed of the video content. Valid forms for the URL include at least: - https://www.youtube.com/watch?v=YOUTUBE_ID - https://www.youtube.com/embed/YOUTUBE_ID - https://youtu.be/YOUTUBE_ID Features like start time (`?t=45`) are currently not supported.
1 parent 1914454 commit bbcb8c0

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

doc/conf.py

+9
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@
4343
except ImportError:
4444
pass
4545

46+
import sys
47+
sys.path.insert(0, '.')
48+
try:
49+
# Load our YouTube directive
50+
import youtube_directive
51+
extensions.append('youtube_directive')
52+
except ImportError:
53+
pass
54+
4655
# External links mappings for extlinks
4756
# see: http://www.sphinx-doc.org/en/master/usage/extensions/extlinks.html
4857
extlinks = {

doc/youtube_directive.py

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# $Id: misc.py 8257 2019-06-24 17:11:29Z milde $
2+
# Authors: David Goodger <[email protected]>; Dethe Elza
3+
# Copyright: This module has been placed in the public domain.
4+
5+
"""Miscellaneous directives."""
6+
7+
__docformat__ = 'reStructuredText'
8+
__version__ = "0.1.0"
9+
10+
import sys
11+
import re
12+
from docutils import nodes
13+
from docutils.parsers.rst import directives
14+
from docutils.utils.error_reporting import ErrorString
15+
16+
from sphinx import addnodes
17+
from sphinx.util import parselinenos
18+
from sphinx.util.docutils import SphinxDirective
19+
20+
if False:
21+
# For type annotation
22+
from typing import Any, Dict, List, Tuple # NOQA
23+
from sphinx.application import Sphinx # NOQA
24+
from sphinx.config import Config # NOQA
25+
26+
27+
class Youtube(SphinxDirective):
28+
29+
"""
30+
Wrap YouTube URLs in embedding HTML
31+
32+
Content is included in output based on type argument
33+
34+
Content may be included inline (content section of directive) or
35+
imported from a file or url.
36+
"""
37+
38+
embed_template = """
39+
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; height: auto;">
40+
<iframe src="{url}" frameborder="0" allowfullscreen style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe>
41+
</div>
42+
"""
43+
44+
required_arguments = 1
45+
optional_arguments = 0
46+
final_argument_whitespace = True
47+
option_spec = {'target': directives.unchanged_required,
48+
'encoding': directives.encoding}
49+
has_content = True
50+
51+
def run(self):
52+
if not self.state.document.settings.raw_enabled:
53+
raise self.warning('"%s" directive disabled.' % self.name)
54+
attributes = {'format': 'html'}
55+
encoding = self.options.get(
56+
'encoding', self.state.document.settings.input_encoding)
57+
e_handler=self.state.document.settings.input_encoding_error_handler
58+
if self.content:
59+
raise self.error(
60+
'"%s" directive may not have content.' % self.name)
61+
62+
target = self.arguments[0]
63+
64+
id = ""
65+
try:
66+
results = re.match(
67+
r'https.*(embed/|/|\?v=)(?P<ID>[a-zA-Z0-9_-]*)(?:/?)$',
68+
target)
69+
if results and 'ID' in results.groupdict():
70+
id = results.group('ID')
71+
else:
72+
id = target
73+
except AttributeError:
74+
pass
75+
76+
try:
77+
url = 'https://www.youtube.com/embed/{id}'.format(id=id)
78+
text = self.embed_template.format(url=url)
79+
except UnicodeError as error:
80+
raise self.severe('Problem with "%s" directive:\n%s'
81+
% (self.name, ErrorString(error)))
82+
83+
raw_node = nodes.raw('', text, **attributes)
84+
(raw_node.source, raw_node.line) = \
85+
self.state_machine.get_source_and_line(self.lineno)
86+
return [raw_node]
87+
88+
89+
def setup(app):
90+
# type: (Sphinx) -> Dict[str, Any]
91+
directives.register_directive('youtube', Youtube)
92+
93+
return {
94+
'version': __version__,
95+
'parallel_read_safe': True,
96+
'parallel_write_safe': True,
97+
}

0 commit comments

Comments
 (0)