Coverage for pyquickhelper/sphinxext/revealjs/directives.py: 100%

152 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-03 02:21 +0200

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

2""" 

3 sphinxjp.themes.revealjs.directives 

4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

5 

6 :author: tell-k <ffk2005@gmail.com> 

7 :copyright: tell-k. All Rights Reserved. 

8""" 

9from docutils import nodes 

10from docutils.parsers.rst import directives 

11from docutils.parsers.rst.roles import set_classes 

12from docutils.parsers.rst import Directive 

13from . import compat 

14 

15__docformat__ = 'reStructuredText' 

16 

17 

18class revealjs(nodes.General, nodes.Element): 

19 """ node for revealjs """ 

20 

21 

22class rv_code(nodes.General, nodes.Element): 

23 """ node for revealjs code section """ 

24 

25 

26class rv_small(nodes.General, nodes.Element): 

27 """ node for revealjs small text section """ 

28 

29 

30class rv_note(nodes.General, nodes.Element): 

31 """ node for revealjs presentation note """ 

32 

33 

34def heading(argument): 

35 """ directives choices for heading tag """ 

36 return directives.choice(argument, ('h1', 'h2', 'h3', 'h4', 'h5', 'h6')) 

37 

38 

39class RevealjsDirective(Directive): 

40 """ Reveal.JS slide entry """ 

41 

42 has_content = True 

43 required_arguments = 0 

44 optional_arguments = 100 

45 final_argument_whitespace = False 

46 

47 option_spec = { 

48 'id': directives.unchanged, 

49 'class': directives.class_option, 

50 'noheading': directives.flag, 

51 'title-heading': heading, 

52 'subtitle': directives.unchanged, 

53 'subtitle-heading': directives.unchanged, 

54 'data-autoslide': directives.unchanged, 

55 'data-markdown': directives.unchanged, 

56 'data-transition': directives.unchanged, 

57 'data-transition-speed': directives.unchanged, 

58 'data-background': directives.unchanged, 

59 'data-background-repeat': directives.unchanged, 

60 'data-background-size': directives.unchanged, 

61 'data-background-transition': directives.unchanged, 

62 'data-state': directives.unchanged, 

63 'data-separator': directives.unchanged, 

64 'data-separator-vertical': directives.unchanged, 

65 'data-separator-notes': directives.unchanged, 

66 'data-charset': directives.unchanged, 

67 } 

68 

69 node_class = revealjs 

70 

71 def run(self): 

72 """ build revealjs node """ 

73 

74 set_classes(self.options) 

75 

76 text = '\n'.join(self.content) 

77 node = self.node_class(text, **self.options) 

78 

79 self.add_name(node) 

80 

81 if "data-markdown" not in self.options: 

82 self.state.nested_parse(self.content, self.content_offset, node) 

83 

84 if self.arguments: 

85 node['title'] = " ".join(self.arguments) 

86 

87 node['noheading'] = ('noheading' in self.options) 

88 

89 options_list = ( 

90 'id', 

91 'title-heading', 

92 'subtitle-heading', 

93 'data-autoslide', 

94 'data-transition', 

95 'data-transition-speed', 

96 'data-background', 

97 'data-background-repeat', 

98 'data-background-size', 

99 'data-background-transition', 

100 'data-state', 

101 'data-markdown', 

102 'data-separator', 

103 'data-separator-vertical', 

104 'data-separator-notes', 

105 'data-charset', 

106 ) 

107 for option in options_list: 

108 if option in self.options: 

109 node[option] = self.options.get(option) 

110 return [node] 

111 

112 

113class RvSmallDirective(Directive): 

114 """ 

115 Create small text tag. 

116 """ 

117 has_content = True 

118 required_arguments = 0 

119 optional_arguments = 0 

120 final_argument_whitespace = False 

121 

122 option_spec = { 

123 'class': directives.class_option, 

124 } 

125 node_class = rv_small 

126 

127 def run(self): 

128 """ build rv_small node """ 

129 

130 set_classes(self.options) 

131 self.assert_has_content() 

132 text = '\n'.join(self.content) 

133 node = self.node_class(text, **self.options) 

134 self.add_name(node) 

135 self.state.nested_parse(self.content, self.content_offset, node) 

136 return [node] 

137 

138 

139class RvNoteDirective(Directive): 

140 """ 

141 Directive for a notes tag. 

142 """ 

143 has_content = True 

144 required_arguments = 0 

145 optional_arguments = 0 

146 final_argument_whitespace = False 

147 

148 option_spec = { 

149 'class': directives.class_option, 

150 } 

151 node_class = rv_note 

152 

153 def run(self): 

154 """ build rv_note node """ 

155 set_classes(self.options) 

156 self.assert_has_content() 

157 text = '\n'.join(self.content) 

158 node = self.node_class(text, **self.options) 

159 self.add_name(node) 

160 self.state.nested_parse(self.content, self.content_offset, node) 

161 return [node] 

162 

163 

164class RvCodeDirective(Directive): 

165 """ 

166 Directive for a code block with highlight.js 

167 """ 

168 

169 has_content = True 

170 required_arguments = 0 

171 optional_arguments = 0 

172 final_argument_whitespace = False 

173 option_spec = { 

174 'id': directives.unchanged, 

175 'class': directives.class_option, 

176 } 

177 node_class = rv_code 

178 

179 def run(self): 

180 """ build rv_code node """ 

181 set_classes(self.options) 

182 self.assert_has_content() 

183 node = self.node_class('\n'.join(self.content), **self.options) 

184 return [node] 

185 

186 

187def visit_revealjs(self, node): 

188 """ build start tag for revealjs """ 

189 section_attr = {} 

190 markdown_headings = {"h1": "#", "h2": "##", "h3": "###", 

191 "h4": "####", "h5": "#####", "h6": "######"} 

192 

193 if node.get("id"): 

194 section_attr.update({"ids": [node.get("id")]}) 

195 

196 attr_list = ( 

197 'data-autoslide', 

198 'data-transition', 

199 'data-transition-speed', 

200 'data-background', 

201 'data-background-repeat', 

202 'data-background-size', 

203 'data-background-transition', 

204 'data-state', 

205 'data-markdown', 

206 'data-separator', 

207 'data-separator-vertical', 

208 'data-separator-notes', 

209 'data-charset', 

210 ) 

211 for attr in attr_list: 

212 if node.get(attr) is not None: 

213 section_attr.update({attr: node.get(attr)}) 

214 

215 title = None 

216 if node.get("title") and not node.get('noheading'): 

217 title = node.get("title") 

218 

219 title_heading = node.get('title-heading', 'h2') 

220 subtitle = node.get("subtitle") 

221 subtitle_heading = node.get('subtitle-heading', 'h3') 

222 if node.get("data-markdown") is not None: 

223 

224 title_base = compat.text("%(heading)s %(title)s \n") 

225 title_text = None 

226 if title: 

227 title_text = title_base % dict( 

228 heading=markdown_headings.get(title_heading), 

229 title=title 

230 ) 

231 

232 subtitle_text = None 

233 if subtitle: 

234 subtitle_text = title_base % dict( 

235 heading=markdown_headings.get(subtitle_heading), 

236 title=subtitle 

237 ) 

238 else: 

239 title_base = compat.text("<%(heading)s>%(title)s</%(heading)s>\n") 

240 title_text = None 

241 if title: 

242 title_text = title_base % dict( 

243 title=title, 

244 heading=title_heading) 

245 

246 subtitle_text = None 

247 if subtitle: 

248 subtitle_text = title_base % dict( 

249 title=subtitle, 

250 heading=subtitle_heading) 

251 

252 if node.get("data-markdown") is not None: 

253 self.body.append(self.starttag(node, 'section', **section_attr)) 

254 if node.get("data-markdown") == compat.text(""): 

255 self.body.append("<script type='text/template'>\n") 

256 if title_text: 

257 self.body.append(title_text) 

258 if subtitle_text: 

259 self.body.append(subtitle_text) 

260 self.body.append(node.rawsource) 

261 self.body.append("</script>\n") 

262 else: 

263 self.body.append(self.starttag(node, 'section', **section_attr)) 

264 if title_text: 

265 self.body.append(title_text) 

266 if subtitle_text: 

267 self.body.append(subtitle_text) 

268 self.set_first_last(node) 

269 

270 

271def depart_revealjs(self, node=None): 

272 """ build end tag for revealjs """ 

273 self.body.append('</section>\n') 

274 

275 

276def visit_rv_code(self, node): 

277 """ build start tag for rv_code """ 

278 

279 self.body.append(self.starttag(node, 'pre')) 

280 self.body.append("<code data-trim contenteditable>") 

281 self.body.append(compat.escape_html(node.rawsource)) 

282 

283 

284def depart_rv_code(self, node=None): 

285 """ build end tag for rv_code """ 

286 

287 self.body.append("</code>") 

288 self.body.append("</pre>\n") 

289 

290 

291def visit_rv_small(self, node): 

292 """ build start tag for rv_small """ 

293 self.body.append(self.starttag(node, 'small')) 

294 self.set_first_last(node) 

295 

296 

297def depart_rv_small(self, node=None): 

298 """ build end tag for rv_small""" 

299 self.body.append("</small>\n") 

300 

301 

302def visit_rv_note(self, node): 

303 """ build start tag for rv_note """ 

304 self.body.append(self.starttag(node, 'aside', **{'class': 'notes'})) 

305 self.set_first_last(node) 

306 

307 

308def depart_rv_note(self, node=None): 

309 """ build end tag for rv_note """ 

310 self.body.append("</aside>\n") 

311 

312 

313def setup(app): 

314 """Initialize """ 

315 app.add_node(revealjs, html=(visit_revealjs, depart_revealjs)) 

316 app.add_node(rv_code, html=(visit_rv_code, depart_rv_code)) 

317 app.add_node(rv_note, html=(visit_rv_note, depart_rv_note)) 

318 app.add_node(rv_small, html=(visit_rv_small, depart_rv_small)) 

319 app.add_directive('revealjs', RevealjsDirective) 

320 app.add_directive('rv_code', RvCodeDirective) 

321 app.add_directive('rv_note', RvNoteDirective) 

322 app.add_directive('rv_small', RvSmallDirective) 

323 return app