link-roles.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. # based on http://protips.readthedocs.io/link-roles.html
  2. from __future__ import print_function
  3. from __future__ import unicode_literals
  4. import re
  5. import os
  6. from docutils import nodes
  7. from local_util import run_cmd_get_output
  8. from sphinx.transforms.post_transforms import SphinxPostTransform
  9. def get_github_rev():
  10. path = run_cmd_get_output('git rev-parse --short HEAD')
  11. tag = run_cmd_get_output('git describe --exact-match')
  12. print('Git commit ID: ', path)
  13. if len(tag):
  14. print('Git tag: ', tag)
  15. path = tag
  16. return path
  17. def setup(app):
  18. rev = get_github_rev()
  19. # links to files or folders on the GitHub
  20. baseurl = 'https://github.com/espressif/esp-idf'
  21. app.add_role('idf', autolink('{}/tree/{}/%s'.format(baseurl, rev)))
  22. app.add_role('idf_file', autolink('{}/blob/{}/%s'.format(baseurl, rev)))
  23. app.add_role('idf_raw', autolink('{}/raw/{}/%s'.format(baseurl, rev)))
  24. app.add_role('component', autolink('{}/tree/{}/components/%s'.format(baseurl, rev)))
  25. app.add_role('component_file', autolink('{}/blob/{}/components/%s'.format(baseurl, rev)))
  26. app.add_role('component_raw', autolink('{}/raw/{}/components/%s'.format(baseurl, rev)))
  27. app.add_role('example', autolink('{}/tree/{}/examples/%s'.format(baseurl, rev)))
  28. app.add_role('example_file', autolink('{}/blob/{}/examples/%s'.format(baseurl, rev)))
  29. app.add_role('example_raw', autolink('{}/raw/{}/examples/%s'.format(baseurl, rev)))
  30. # link to the current documentation file in specific language version
  31. app.add_role('link_to_translation', link_to_translation)
  32. app.add_node(translation_link)
  33. app.add_post_transform(TranslationLinkNodeTransform)
  34. class translation_link(nodes.Element):
  35. """Node for "link_to_translation" role."""
  36. # Linking to translation is done at the "writing" stage to avoid issues with the info being cached between builders
  37. def link_to_translation(name, rawtext, text, lineno, inliner, options={}, content=[]):
  38. node = translation_link()
  39. node['expr'] = (rawtext, text, options)
  40. return [node], []
  41. class TranslationLinkNodeTransform(SphinxPostTransform):
  42. # Transform needs to happen early to ensure the new reference node is also transformed
  43. default_priority = 0
  44. def run(self, **kwargs):
  45. # Only output relative links if building HTML
  46. for node in self.document.traverse(translation_link):
  47. if 'html' in self.app.builder.name:
  48. rawtext, text, options = node['expr']
  49. (language, link_text) = text.split(':')
  50. env = self.document.settings.env
  51. docname = env.docname
  52. doc_path = env.doc2path(docname, None, None)
  53. return_path = '../' * doc_path.count('/') # path back to the root from 'docname'
  54. # then take off 2 more paths for language/release/ and build the new URL
  55. url = '{}.html'.format(os.path.join(return_path, '../..', language, env.config.release, docname))
  56. node.replace_self(nodes.reference(rawtext, link_text, refuri=url, **options))
  57. else:
  58. node.replace_self([])
  59. def autolink(pattern):
  60. def role(name, rawtext, text, lineno, inliner, options={}, content=[]):
  61. m = re.search('(.*)\s*<(.*)>', text) # noqa: W605 - regular expression
  62. if m:
  63. link_text = m.group(1)
  64. link = m.group(2)
  65. else:
  66. link_text = text
  67. link = text
  68. url = pattern % (link,)
  69. node = nodes.reference(rawtext, link_text, refuri=url, **options)
  70. return [node], []
  71. return role
  72. def crosslink(pattern):
  73. def role(name, rawtext, text, lineno, inliner, options={}, content=[]):
  74. (language, link_text) = text.split(':')
  75. docname = inliner.document.settings.env.docname
  76. doc_path = inliner.document.settings.env.doc2path(docname, None, None)
  77. return_path = '../' * doc_path.count('/')
  78. url = pattern % (return_path, language, docname)
  79. node = nodes.reference(rawtext, link_text, refuri=url, **options)
  80. return [node], []
  81. return role