codeblock.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import os
  2. from docutils.parsers.rst import directives
  3. from sphinx.directives.code import CodeBlock
  4. import hashlib
  5. class ExportableCodeBlock(CodeBlock):
  6. option_spec = {
  7. 'summary': directives.unchanged,
  8. 'name': directives.unchanged,
  9. }
  10. names = set()
  11. @staticmethod
  12. def md5(str_data):
  13. t = hashlib.md5()
  14. t.update(str_data.encode('utf-8'))
  15. return t.hexdigest()
  16. def run(self):
  17. if self.env.app.builder.name == 'gettext':
  18. return super().run()
  19. code_save_path = os.environ.get('CODE_EXPORT_PATH')
  20. caption = self.options.get('summary', '')
  21. if code_save_path and not os.path.exists(code_save_path):
  22. os.mkdir(code_save_path)
  23. code_id = self.md5('\n'.join(self.content))[-5:]
  24. if self.options.get('name', None) is None:
  25. # 设置name属性,从而让生成的代码html块具有id属性
  26. self.options.update({'name': 'demo-' + code_id})
  27. else:
  28. name = self.options.get('name', '')
  29. self.options.update({'name': 'demo-' + name})
  30. name = self.options.get('name').replace('_', '-')
  31. if name in type(self).names:
  32. name += '-' + code_id
  33. self.options.update({'name': name})
  34. else:
  35. type(self).names.add(name)
  36. # 设置特殊class值,用于在js中搜索
  37. classes = self.options.get('class', [])
  38. classes.append('demo-cb')
  39. self.options.update({'class': classes})
  40. raw_content_text = '\n'.join(self.content)
  41. content, self.content = self.content, []
  42. for c in content:
  43. if '..demo-only' in c or '## ----' in c:
  44. continue
  45. c = c.replace('# ..doc-only', '')
  46. self.content.append(c)
  47. nodes = super().run()
  48. try:
  49. elem_id = nodes[0]['ids'][0]
  50. except IndexError:
  51. elem_id = None
  52. if code_save_path and elem_id:
  53. fpath = os.path.join(code_save_path, elem_id)
  54. open(fpath, 'w').write(caption + '\n\n' + raw_content_text)
  55. return nodes
  56. def setup(app):
  57. app.add_directive("exportable-codeblock", ExportableCodeBlock)
  58. app.add_js_file('pywebio.js')
  59. return {
  60. 'version': '0.1',
  61. 'parallel_read_safe': True,
  62. 'parallel_write_safe': True,
  63. }