]> git.proxmox.com Git - proxmox-backup.git/blob - docs/_ext/proxmox-scanrefs.py
scanrefs: match all instances of 'onlineHelp' in js files
[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 allmatch = re.findall("onlineHelp:\s*[\'\"](.*?)[\'\"]", fd, re.M)
48 for match in allmatch:
49 anchor = match
50 anchor = re.sub('_', '-', anchor) # normalize labels
51 logger.info("found onlineHelp: {} in {}".format(anchor, js_file))
52 used_anchors.append(anchor)
53
54 return used_anchors
55
56
57 def setup(app):
58 logger.info('Mapping reference labels...')
59 app.add_builder(ReflabelMapper)
60 return {
61 'version': '0.1',
62 'parallel_read_safe': True,
63 'parallel_write_safe': True,
64 }
65
66 class ReflabelMapper(Builder):
67 name = 'proxmox-scanrefs'
68
69 def init(self):
70 self.docnames = []
71 self.env.online_help = {}
72 self.env.online_help['pbs_documentation_index'] = {
73 'link': '/docs/index.html',
74 'title': 'Proxmox Backup Server Documentation Index',
75 }
76 self.env.used_anchors = scan_extjs_files()
77
78 if not os.path.isdir(self.outdir):
79 os.mkdir(self.outdir)
80
81 self.output_filename = os.path.join(self.outdir, 'OnlineHelpInfo.js')
82 self.output = io.open(self.output_filename, 'w', encoding='UTF-8')
83
84 def write_doc(self, docname, doctree):
85 for node in doctree.traverse(nodes.section):
86 #pprint(vars(node))
87
88 if hasattr(node, 'expect_referenced_by_id') and len(node['ids']) > 1: # explicit labels
89 filename = self.env.doc2path(docname)
90 filename_html = re.sub('.rst', '.html', filename)
91 labelid = node['ids'][1] # [0] is predefined by sphinx, we need [1] for explicit ones
92 title = cast(nodes.title, node[0])
93 logger.info('traversing section {}'.format(title.astext()))
94 ref_name = getattr(title, 'rawsource', title.astext())
95
96 self.env.online_help[labelid] = {'link': '', 'title': ''}
97 self.env.online_help[labelid]['link'] = "/docs/" + os.path.basename(filename_html) + "#{}".format(labelid)
98 self.env.online_help[labelid]['title'] = ref_name
99
100 return
101
102
103 def get_outdated_docs(self):
104 return 'all documents'
105
106 def prepare_writing(self, docnames):
107 return
108
109 def get_target_uri(self, docname, typ=None):
110 return ''
111
112 def validate_anchors(self):
113 #pprint(self.env.online_help)
114 to_remove = []
115 for anchor in self.env.used_anchors:
116 if anchor not in self.env.online_help:
117 logger.info("[-] anchor {} is missing from onlinehelp!".format(anchor))
118 for anchor in self.env.online_help:
119 if anchor not in self.env.used_anchors and anchor != 'pbs_documentation_index':
120 logger.info("[*] anchor {} not used! deleting...".format(anchor))
121 to_remove.append(anchor)
122 for anchor in to_remove:
123 self.env.online_help.pop(anchor, None)
124 return
125
126 def finish(self):
127 # generate OnlineHelpInfo.js output
128 self.validate_anchors()
129
130 self.output.write("const proxmoxOnlineHelpInfo = ")
131 self.output.write(json.dumps(self.env.online_help, indent=2))
132 self.output.write(";\n")
133 self.output.close()
134 return