1
0

codeblock.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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. code_save_path = os.environ.get('CODE_EXPORT_PATH')
  18. caption = self.options.get('summary', '')
  19. if code_save_path and not os.path.exists(code_save_path):
  20. os.mkdir(code_save_path)
  21. code_id = self.md5('\n'.join(self.content))[-5:]
  22. if self.options.get('name', None) is None:
  23. # 设置name属性,从而让生成的代码html块具有id属性
  24. self.options.update({'name': 'demo-' + code_id})
  25. name = self.options.get('name').replace('_','-')
  26. if name in type(self).names:
  27. name += '-' + code_id
  28. self.options.update({'name': name})
  29. else:
  30. type(self).names.add(name)
  31. # 设置特殊class值,用于在js中搜索
  32. classes = self.options.get('class', [])
  33. classes.append('demo-cb')
  34. self.options.update({'class': classes})
  35. raw_content_text = '\n'.join(self.content)
  36. content, self.content = self.content, []
  37. for c in content:
  38. if '..demo-only' in c or '## ----' in c:
  39. continue
  40. c = c.replace('# ..doc-only', '')
  41. self.content.append(c)
  42. nodes = super().run()
  43. try:
  44. elem_id = nodes[0]['ids'][0]
  45. except IndexError:
  46. elem_id = None
  47. if code_save_path and elem_id:
  48. fpath = os.path.join(code_save_path, elem_id)
  49. open(fpath, 'w').write(caption + '\n\n' + raw_content_text)
  50. return nodes
  51. def setup(app):
  52. app.add_directive("exportable-codeblock", ExportableCodeBlock)
  53. app.add_js_file('pywebio.js')
  54. return {
  55. 'version': '0.1',
  56. 'parallel_read_safe': True,
  57. 'parallel_write_safe': True,
  58. }