]> git.proxmox.com Git - proxmox-backup.git/blob - docs/_ext/proxmox-scanrefs.py
dd88f462da268a68a5281c7db0bdc91ff974be86
[proxmox-backup.git] / docs / _ext / proxmox-scanrefs.py
1 #!/usr/bin/env python3
2
3 # debugging stuff
4 from pprint import pprint
5
6 from typing import cast
7
8 import json
9 import re
10
11 import os
12 import io
13 from docutils import nodes
14
15 from sphinx.builders import Builder
16 from sphinx.util import logging
17
18 logger = logging.getLogger(__name__)
19
20 # refs are added in the following manner before the title of a section (note underscore and newline before title):
21 # .. _my-label:
22 #
23 # Section to ref
24 # --------------
25 #
26 #
27 # then referred to like (note missing underscore):
28 # "see :ref:`my-label`"
29 #
30 # the benefit of using this is if a label is explicitly set for a section,
31 # we can refer to it with this anchor #my-label in the html,
32 # even if the section name changes.
33 #
34 # see https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-ref
35
36 def scan_extjs_files(wwwdir="../www"): # a bit rough i know, but we can optimize later
37 js_files = []
38 used_anchors = []
39 logger.info("scanning extjs files for onlineHelp definitions")
40 for root, dirs, files in os.walk("{}".format(wwwdir)):
41 #print(root, dirs, files)
42 for filename in files:
43 if filename.endswith('.js'):
44 js_files.append(os.path.join(root, filename))
45 for js_file in js_files:
46 fd = open(js_file).read()
47 match = re.search("onlineHelp:\s*[\'\"](.*?)[\'\"]", fd) # match object is tuple
48 if match:
49 anchor = match.groups()[0]
50 anchor = re.sub('_', '-', anchor) # normalize labels
51 logger.info("found onlineHelp: {} in {}".format(anchor, js_file))
52 used_anchors.append(anchor)
53 return used_anchors
54
55
56 def setup(app):
57 logger.info('Mapping reference labels...')
58 app.add_builder(ReflabelMapper)
59 return {
60 'version': '0.1',
61 'parallel_read_safe': True,
62 'parallel_write_safe': True,
63 }
64
65 class ReflabelMapper(Builder):
66 name = 'proxmox-scanrefs'
67
68 def init(self):
69 self.docnames = []
70 self.env.online_help = {}
71 self.env.online_help['pbs_documentation_index'] = {
72 'link': '/docs/index.html',
73 'title': 'Proxmox Backup Server Documentation Index',
74 }
75 self.env.used_anchors = scan_extjs_files()
76
77 if not os.path.isdir(self.outdir):
78 os.mkdir(self.outdir)
79
80 self.output_filename = os.path.join(self.outdir, 'OnlineHelpInfo.js')
81 self.output = io.open(self.output_filename, 'w', encoding='UTF-8')
82
83 def write_doc(self, docname, doctree):
84 for node in doctree.traverse(nodes.section):
85 #pprint(vars(node))
86
87 if hasattr(node, 'expect_referenced_by_id') and len(node['ids']) > 1: # explicit labels
88 filename = self.env.doc2path(docname)
89 filename_html = re.sub('.rst', '.html', filename)
90 labelid = node['ids'][1] # [0] is predefined by sphinx, we need [1] for explicit ones
91 title = cast(nodes.title, node[0])
92 logger.info('traversing section {}'.format(title.astext()))
93 ref_name = getattr(title, 'rawsource', title.astext())
94
95 self.env.online_help[labelid] = {'link': '', 'title': ''}
96 self.env.online_help[labelid]['link'] = "/docs/" + os.path.basename(filename_html) + "#{}".format(labelid)
97 self.env.online_help[labelid]['title'] = ref_name
98
99 return
100
101
102 def get_outdated_docs(self):
103 return 'all documents'
104
105 def prepare_writing(self, docnames):
106 return
107
108 def get_target_uri(self, docname, typ=None):
109 return ''
110
111 def validate_anchors(self):
112 #pprint(self.env.online_help)
113 to_remove = []
114 for anchor in self.env.used_anchors:
115 if anchor not in self.env.online_help:
116 logger.info("[-] anchor {} is missing from onlinehelp!".format(anchor))
117 for anchor in self.env.online_help:
118 if anchor not in self.env.used_anchors and anchor != 'pbs_documentation_index':
119 logger.info("[*] anchor {} not used! deleting...".format(anchor))
120 to_remove.append(anchor)
121 for anchor in to_remove:
122 self.env.online_help.pop(anchor, None)
123 return
124
125 def finish(self):
126 # generate OnlineHelpInfo.js output
127 self.validate_anchors()
128
129 self.output.write("const proxmoxOnlineHelpInfo = ")
130 self.output.write(json.dumps(self.env.online_help, indent=2))
131 self.output.write(";\n")
132 self.output.close()
133 return