backport default into stable. STABLE IS NOW 3.9, default 3.10
#!/usr/bin/env python"""Parser for Javascript comments."""from__future__importwith_statementimportsys,os,getopt,redefclean_comment(match):comment=match.group()comment=strip_stars(comment)returncomment# Rest utilitiesdefrest_title(title,level,level_markups=['=','=','-','~','+','`']):size=len(title)iflevel==0:return'\n'.join((level_markups[level]*size,title,level_markups[0]*size))+'\n'return'\n'.join(('\n'+title,level_markups[level]*size))+'\n'defget_doc_comments(text):""" Return a list of all documentation comments in the file text. Each comment is a pair, with the first element being the comment text and the second element being the line after it, which may be needed to guess function & arguments. >>> get_doc_comments(read_file('examples/module.js'))[0][0][:40] '/**\n * This is the module documentation.' >>> get_doc_comments(read_file('examples/module.js'))[1][0][7:50] 'This is documentation for the first method.' >>> get_doc_comments(read_file('examples/module.js'))[1][1] 'function the_first_function(arg1, arg2) ' >>> get_doc_comments(read_file('examples/module.js'))[2][0] '/** This is the documentation for the second function. */' """return[clean_comment(match)formatchinre.finditer('/\*\*.*?\*/',text,re.DOTALL|re.MULTILINE)]RE_STARS=re.compile('^\s*?\* ?',re.MULTILINE)defstrip_stars(doc_comment):""" Strip leading stars from a doc comment. >>> strip_stars('/** This is a comment. */') 'This is a comment.' >>> strip_stars('/**\n * This is a\n * multiline comment. */') 'This is a\n multiline comment.' >>> strip_stars('/** \n\t * This is a\n\t * multiline comment. \n*/') 'This is a\n multiline comment.' """returnRE_STARS.sub('',doc_comment[3:-2]).strip()defparse_js_files(args=sys.argv):""" Main command-line invocation. """try:opts,args=getopt.gnu_getopt(args[1:],'p:o:h',['jspath=','output=','help'])opts=dict(opts)exceptgetopt.GetoptError:usage()sys.exit(2)rst_dir=opts.get('--output')oropts.get('-o')ifrst_dirisNoneandlen(args)!=1:rst_dir='apidocs'js_dir=opts.get('--jspath')oropts.get('-p')ifnotos.path.exists(os.path.join(rst_dir)):os.makedirs(os.path.join(rst_dir))f_index=open(os.path.join(rst_dir,'index.rst'),'wb')f_index.write('''.. toctree:: :maxdepth: 1''')forjs_path,js_dirs,js_filesinos.walk(js_dir):rst_path=re.sub('%s%s*'%(js_dir,os.path.sep),'',js_path)forjs_fileinjs_files:ifnotjs_file.endswith('.js'):continueifnotos.path.exists(os.path.join(rst_dir,rst_path)):os.makedirs(os.path.join(rst_dir,rst_path))rst_content=extract_rest(js_path,js_file)filename=os.path.join(rst_path,js_file[:-3])# add to indexf_index.write(' %s\n'%filename)# save rst filewithopen(os.path.join(rst_dir,filename)+'.rst','wb')asf_rst:f_rst.write(rst_content)f_index.close()defextract_rest(js_dir,js_file):js_filepath=os.path.join(js_dir,js_file)filecontent=open(js_filepath,'U').read()comments=get_doc_comments(filecontent)rst=rest_title(js_file,0)rst+='.. module:: %s\n\n'%js_filerst+='\n\n'.join(comments)returnrstif__name__=='__main__':parse_js_files()