Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2""" 

3@file 

4@brief Inspired from `sphinxcontrib.youtube <https://github.com/thewtex/sphinx-contrib/blob/master/youtube/sphinxcontrib/youtube.py>`_ 

5(not maintained anymore). 

6""" 

7import re 

8import sphinx 

9from docutils import nodes 

10from docutils.parsers.rst import Directive, directives 

11from sphinx.util import logging 

12 

13CONTROL_HEIGHT = 30 

14 

15 

16def get_size(d, key): 

17 """ 

18 Get size. 

19 

20 @param d string 

21 @param key string 

22 @return integer 

23 """ 

24 if key not in d: 

25 return None 

26 m = re.match("(\\d+)(|%|px)$", d[key]) 

27 if not m: 

28 raise ValueError("invalid size %r" % d[key]) 

29 return int(m.group(1)), m.group(2) or "px" 

30 

31 

32def css(d): 

33 """ 

34 Returns style. 

35 """ 

36 return "; ".join(sorted("%s: %s" % kv for kv in d.items())) 

37 

38 

39class youtube_node(nodes.General, nodes.Element): 

40 """ 

41 Youtube node. 

42 """ 

43 pass 

44 

45 

46def visit_youtube_node(self, node): 

47 """ 

48 Visit youtube node (html). 

49 """ 

50 aspect = node["aspect"] 

51 width = node["width"] 

52 height = node["height"] 

53 

54 if aspect is None: 

55 aspect = 16, 9 

56 

57 if hasattr(self, "starttag"): 

58 if (height is None) and (width is not None) and (width[1] == "%"): 

59 style = { 

60 "padding-top": "%dpx" % CONTROL_HEIGHT, 

61 "padding-bottom": "%f%%" % (width[0] * aspect[1] / aspect[0]), 

62 "width": "%d%s" % width, 

63 "position": "relative", 

64 } 

65 self.body.append(self.starttag(node, "div", style=css(style))) 

66 style = { 

67 "position": "absolute", 

68 "top": "0", 

69 "left": "0", 

70 "width": "100%", 

71 "height": "100%", 

72 "border": "0", 

73 } 

74 attrs = { 

75 "src": "https://www.youtube.com/embed/%s" % node["id"], 

76 "style": css(style), 

77 } 

78 self.body.append(self.starttag(node, "iframe", **attrs)) 

79 self.body.append("</iframe></div>") 

80 else: 

81 if width is None: 

82 if height is None: 

83 width = 560, "px" 

84 else: 

85 width = height[0] * aspect[0] / aspect[1], "px" 

86 if height is None: 

87 height = width[0] * aspect[1] / aspect[0], "px" 

88 style = { 

89 "width": "%d%s" % width, 

90 "height": "%d%s" % (height[0] + CONTROL_HEIGHT, height[1]), 

91 "border": "0", 

92 } 

93 attrs = { 

94 "src": "https://www.youtube.com/embed/%s" % node["id"], 

95 "style": css(style), 

96 } 

97 self.body.append(self.starttag(node, "iframe", **attrs)) 

98 self.body.append("</iframe>") 

99 else: 

100 self.body.append("https://www.youtube.com/embed/%s" % node["id"]) 

101 

102 

103def depart_youtube_node(self, node): 

104 """ 

105 Youtube node. 

106 """ 

107 pass 

108 

109 

110class YoutubeDirective(Directive): 

111 """ 

112 Youtube directive. 

113 """ 

114 has_content = True 

115 required_arguments = 1 

116 optional_arguments = 0 

117 final_argument_whitespace = False 

118 option_spec = { 

119 "width": directives.unchanged, 

120 "height": directives.unchanged, 

121 "aspect": directives.unchanged, 

122 } 

123 

124 def run(self): 

125 if "aspect" in self.options: 

126 aspect = self.options.get("aspect") 

127 m = re.match("(\\d+):(\\d+)", aspect) 

128 if m is None: 

129 raise ValueError("invalid aspect ratio %r" % aspect) 

130 aspect = tuple(int(x) for x in m.groups()) 

131 else: 

132 aspect = None 

133 width = get_size(self.options, "width") 

134 height = get_size(self.options, "height") 

135 idurl = self.arguments[0] 

136 if "https://" in idurl or "http://" in idurl: 

137 if "watch?v=" in idurl: 

138 uid = idurl.split("watch?v=")[-1] 

139 else: 

140 uid = idurl.split('/')[-1] 

141 if len(uid) <= 4 or '.' in uid: 

142 env = self.state.document.settings.env if hasattr( 

143 self.state.document.settings, "env") else None 

144 logger = logging.getLogger("youtube") 

145 lineno = self.lineno 

146 docname = None if env is None else env.docname 

147 logger.warning( 

148 "[youtube] unable to extract video id from '{0}' in docname '{1}' - line {2}.".format(idurl, docname, lineno)) 

149 uid = "" 

150 else: 

151 uid = self.arguments[0] 

152 return [youtube_node(id=uid, aspect=aspect, width=width, height=height)] 

153 

154 

155def setup(app): 

156 """ 

157 Setup for youtube extension. 

158 """ 

159 app.add_node(youtube_node, 

160 html=(visit_youtube_node, depart_youtube_node), 

161 epub=(visit_youtube_node, depart_youtube_node), 

162 elatex=(visit_youtube_node, depart_youtube_node), 

163 latex=(visit_youtube_node, depart_youtube_node), 

164 rst=(visit_youtube_node, depart_youtube_node), 

165 md=(visit_youtube_node, depart_youtube_node), 

166 text=(visit_youtube_node, depart_youtube_node)) 

167 app.add_directive("youtube", YoutubeDirective) 

168 return {'version': sphinx.__display_version__, 'parallel_read_safe': True}