Changeset 99064 in vbox for trunk/doc/manual/htmlhelp-qthelp.py
- Timestamp:
- Mar 20, 2023 12:01:53 PM (2 years ago)
- svn:sync-xref-src-repo-rev:
- 156429
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/manual/htmlhelp-qthelp.py
r98950 r99064 1 1 #!/usr/bin/python3 2 2 # -*- coding: utf-8 -*- 3 3 # $Id$ 4 ## @file 5 # A python script to create a .qhp file out of a given htmlhelp 6 # folder. Lots of things about the said folder is assumed. Please 7 # see the code and inlined comments. 8 9 import sys, getopt 10 import os.path 11 import re 12 import logging 13 14 if sys.version_info >= (3, 0): 15 from html.parser import HTMLParser 16 else: 17 from HTMLParser import HTMLParser 18 19 4 5 """ 6 A python script to create a .qhp file out of a given htmlhelp 7 folder. Lots of things about the said folder is assumed. Please 8 see the code and inlined comments. 9 """ 20 10 21 11 __copyright__ = \ … … 42 32 """ 43 33 34 import getopt 35 import logging 36 import os.path 37 import re 38 import sys 39 40 if sys.version_info[0] >= 3: 41 from html.parser import HTMLParser 42 else: 43 from HTMLParser import HTMLParser 44 44 45 # number of opened and not yet closed section tags of toc section 45 46 open_section_tags = 0 … … 47 48 html_files = [] 48 49 49 # use html_parser stuff to collect <a name tags50 50 def create_keywords_section(folder): 51 """ 52 use html_parser stuff to collect <a name ...> tags 53 """ 51 54 keywords_section_lines = ['<keywords>'] 52 55 for html_file_name in html_files: … … 55 58 56 59 class html_parser(HTMLParser): 57 def __init__(self):58 HTMLParser.__init__(self)59 self.a_tag=[]60 def handle_starttag(self, tag, attributes):61 if tag != 'div' and tag != 'a':62 return63 if tag == 'a':64 for a in attributes:65 if a[0] == 'name':66 self.a_tag.append(a[1])60 def __init__(self): 61 HTMLParser.__init__(self) 62 self.a_tag = [] 63 def handle_starttag(self, tag, attrs): 64 if tag != 'div' and tag != 'a': 65 return 66 if tag == 'a': 67 for a in attrs: 68 if a[0] == 'name': 69 self.a_tag.append(a[1]) 67 70 68 71 parser = html_parser() … … 70 73 for k in parser.a_tag: 71 74 line = '<keyword name="' + k + '" id="' + k + '" ref="' + html_file_name + '#' + k + '"/>' 72 keywords_section_lines.append(line) ;75 keywords_section_lines.append(line) 73 76 keywords_section_lines.append('</keywords>') 74 77 return keywords_section_lines 75 78 76 # find the png files under /images folder and create a part of the77 # qhelp project file with <file> tags78 79 def create_image_list(folder): 79 image_folder_name = 'images' 80 image_files_list = [] 81 # Look for 'images' sub folder 82 subdirs = [x[0] for x in os.walk(folder)] 83 full_folder_path = os.path.join(folder, image_folder_name) 84 if full_folder_path not in subdirs: 85 logging.error('Image subfolder "%s" is not found under "%s".', image_folder_name, folder) 86 return image_files_list; 87 png_files = [] 88 for f in os.listdir(full_folder_path): 89 png_files.append(image_folder_name + '/' + f) 90 image_files_list.append('<file>images/' + f + '</file>') 91 return image_files_list 92 93 # open files list and read the list of html files from there 80 """ 81 find the png files under topics/images folder and create a part of the 82 qhelp project file with <file> tags 83 """ 84 sFullImageFolderPath = os.path.join(folder, 'topics', 'images'); 85 if not os.path.isdir(sFullImageFolderPath): 86 logging.error('Image subfolder "topics/images" is not found under "%s"!', folder) 87 sys.exit(1); 88 return ['<file>topics/images/%s</file>' % sFile for sFile in os.listdir(sFullImageFolderPath)]; 89 94 90 def create_html_list(folder, list_file): 91 """ 92 open files list and read the list of html files from there 93 """ 95 94 global html_files 96 95 html_file_lines = [] … … 99 98 return html_file_lines 100 99 full_path = os.path.join(folder, list_file) 101 file = open(full_path, encoding='utf-8') 102 103 lines = file.readlines() 104 file.close() 100 with open(full_path, encoding='utf-8') as file: 101 lines = file.readlines() 102 105 103 # first search for the [FILES] marker then collect .html lines 106 104 marker_found = 0 … … 126 124 def parse_param_tag(line): 127 125 label = 'value="' 128 start = line.find(label) ;126 start = line.find(label) 129 127 if start == -1: 130 128 return '' 131 start += 129 start += len(label) 132 130 end = line.find('"', start) 133 131 if end == -1: 134 return '' ;132 return '' 135 133 return line[start:end] 136 134 137 # look at next two lines. they are supposed to look like the following138 # <param name="Name" value="Oracle VM VirtualBox">139 # <param name="Local" value="index.html">140 # parse out value fields and return141 # title="Oracle VM VirtualBox" ref="index.html142 135 def parse_object_tag(lines, index): 143 result='' 136 """ 137 look at next two lines. they are supposed to look like the following 138 <param name="Name" value="Oracle VM VirtualBox"> 139 <param name="Local" value="index.html"> 140 parse out value fields and return 141 title="Oracle VM VirtualBox" ref="index.html 142 """ 143 result = '' 144 144 if index + 2 > len(lines): 145 logging.warning('Not enough tags after this one "%s"', lines[index])145 logging.warning('Not enough tags after this one "%s"', lines[index]) 146 146 return result 147 if not re.match(r'^\s*<param', lines[index + 1], re.IGNORECASE) or\148 not re.match(r'^\s*<param', lines[index + 2], re.IGNORECASE):149 logging.warning('Skipping the line "%s" since next two tags are supposed to be param tags', 147 if not re.match(r'^\s*<param', lines[index + 1], re.IGNORECASE) \ 148 or not re.match(r'^\s*<param', lines[index + 2], re.IGNORECASE): 149 logging.warning('Skipping the line "%s" since next two tags are supposed to be param tags', lines[index]) 150 150 return result 151 151 title = parse_param_tag(lines[index + 1]) … … 159 159 return result 160 160 161 # parse any string other than staring with <OBJECT162 # decide if <session tag should be closed163 161 def parse_non_object_tag(lines, index): 162 """ 163 parse any string other than staring with <OBJECT 164 decide if <section> tag should be closed 165 """ 166 164 167 if index + 1 > len(lines): 165 168 return '' … … 178 181 179 182 def parse_line(lines, index): 180 result =''183 result = '' 181 184 182 185 # if the line starts with <OBJECT … … 187 190 return result 188 191 189 # parse TOC file. assuming all the relevant information190 # is stored in tags and attributes. whatever is outside of191 # <... > pairs is filtered out. we also assume < ..> are not nested192 # and each < matches to a >193 192 def create_toc(folder, toc_file): 193 """ 194 parse TOC file. assuming all the relevant information 195 is stored in tags and attributes. whatever is outside of 196 <... > pairs is filtered out. we also assume < ..> are not nested 197 and each < matches to a > 198 """ 194 199 toc_string_list = [] 195 200 content = [x[2] for x in os.walk(folder)] … … 198 203 return toc_string_list 199 204 full_path = os.path.join(folder, toc_file) 200 file = open(full_path, encoding='utf-8')201 content = file.read()202 file.close() 205 with open(full_path, encoding='utf-8') as file: 206 content = file.read() 207 203 208 # convert the file string into a list of tags there by eliminating whatever 204 209 # char reside outside of tags. … … 219 224 # lines = content.split('\n') 220 225 toc_string_list.append('<toc>') 221 index = 0 222 for tag in tag_list: 226 for index, _ in enumerate(tag_list): 223 227 str = parse_line(tag_list, index) 224 228 if str: 225 229 toc_string_list.append(str) 226 index += 1227 230 toc_string_list.append('</toc>') 228 231 toc_string = '\n'.join(toc_string_list) … … 230 233 return toc_string_list 231 234 232 def usage( arg):235 def usage(iExitCode): 233 236 print('htmlhelp-qthelp.py -d <helphtmlfolder> -o <outputfilename>') 234 sys.exit()237 return iExitCode 235 238 236 239 def main(argv): 240 # Parse arguments. 237 241 helphtmlfolder = '' 238 242 output_filename = '' … … 240 244 toc_file = '' 241 245 try: 242 opts, args = getopt.getopt(sys.argv[1:],"hd:o:f:t:")246 opts, _ = getopt.getopt(argv[1:], "hd:o:f:t:") 243 247 except getopt.GetoptError as err: 244 print(err)245 usage(2)248 logging.error(str(err)) 249 return usage(2) 246 250 for opt, arg in opts: 247 251 if opt == '-h': 248 usage(0)249 elif opt in ("-d"):252 return usage(0) 253 if opt == "-d": 250 254 helphtmlfolder = arg 251 255 print(helphtmlfolder) 252 elif opt in ("-f"):256 elif opt == "-f": 253 257 list_file = arg 254 elif opt in ("-t"):258 elif opt == "-t": 255 259 toc_file = arg 256 260 print(toc_file) 257 elif opt in ("-o"):258 261 elif opt == "-o": 262 output_filename = arg 259 263 # check supplied helphtml folder argument 260 264 if not helphtmlfolder: 261 265 logging.error('No helphtml folder is provided. Exiting') 262 usage(2)266 return usage(2) 263 267 if not os.path.exists(helphtmlfolder): 264 268 logging.error('folder "%s" does not exist. Exiting', helphtmlfolder) 265 usage(2)269 return usage(2) 266 270 helphtmlfolder = os.path.normpath(helphtmlfolder) 267 271 … … 269 273 if not output_filename: 270 274 logging.error('No filename for output is given. Exiting') 271 usage(2)272 273 out_xml_lines = ['<?xml version="1.0" encoding="UTF-8"?>', \274 '<QtHelpProject version="1.0">' , \275 '<namespace>org.virtualbox</namespace>', \276 '<virtualFolder>doc</virtualFolder>', \275 return usage(2) 276 277 out_xml_lines = ['<?xml version="1.0" encoding="UTF-8"?>', 278 '<QtHelpProject version="1.0">', 279 '<namespace>org.virtualbox</namespace>', 280 '<virtualFolder>doc</virtualFolder>', 277 281 '<filterSection>'] 278 out_xml_lines += create_toc(helphtmlfolder, toc_file) + create_files_section(helphtmlfolder, list_file) 282 out_xml_lines += create_toc(helphtmlfolder, toc_file) 283 out_xml_lines += create_files_section(helphtmlfolder, list_file) 279 284 out_xml_lines += create_keywords_section(helphtmlfolder) 280 285 out_xml_lines += ['</filterSection>', '</QtHelpProject>'] 281 286 282 out_file = open(output_filename, 'wb')283 out_file.write('\n'.join(out_xml_lines).encode('utf8'))284 out_file.close()287 with open(output_filename, 'wb') as out_file: 288 out_file.write('\n'.join(out_xml_lines).encode('utf8')) 289 return 0 285 290 286 291 if __name__ == '__main__': 287 main(sys.argv[1:])292 sys.exit(main(sys.argv))
Note:
See TracChangeset
for help on using the changeset viewer.