mirror of
https://github.com/eunomia-bpf/bpf-developer-tutorial.git
synced 2026-02-09 13:15:14 +08:00
197 lines
7.1 KiB
Python
197 lines
7.1 KiB
Python
'''Generate one page API document from rustdoc.
|
|
|
|
This script parses HTML files generated by rustoc and generates a single page API
|
|
document.
|
|
|
|
'''
|
|
from html.parser import HTMLParser
|
|
|
|
pages = ['index.html',
|
|
'struct.BlazeSymbolizer.html',
|
|
'struct.SymbolizedResult.html',
|
|
'enum.SymbolSrcCfg.html',
|
|
'enum.SymbolizerFeature.html',
|
|
'fn.blazesym_new.html',
|
|
'fn.blazesym_free.html',
|
|
'fn.blazesym_symbolize.html',
|
|
'fn.blazesym_result_free.html',
|
|
'struct.blazesym.html',
|
|
'struct.sym_src_cfg.html',
|
|
'enum.blazesym_src_type.html',
|
|
'union.ssc_params.html',
|
|
'struct.ssc_elf.html',
|
|
'struct.ssc_kernel.html',
|
|
'struct.ssc_process.html',
|
|
'struct.blazesym_result.html',
|
|
'struct.blazesym_entry.html',
|
|
'struct.blazesym_csym.html',
|
|
]
|
|
|
|
def replace_text(src, replace, start, stop):
|
|
lines = src.split('\n')
|
|
if start[0] == stop[0]:
|
|
lineno = start[0]
|
|
lines[lineno] = lines[lineno][:start[1]] + replace + lines[lineno][stop[1]:]
|
|
else:
|
|
lines[start[0]] = lines[start[0]][:start[1]]
|
|
lines[stop[0]] = lines[stop[0]][stop[1]:]
|
|
lines[start[0] + 1: stop[0]] = [replace]
|
|
pass
|
|
return '\n'.join(lines)
|
|
|
|
class MyParser(HTMLParser):
|
|
def get_doc_range(self, start, end):
|
|
lines = self.raw_data.split('\n')
|
|
lines = lines[start[0] - 1: end[0]]
|
|
lines[-1] = lines[-1][:end[1]]
|
|
lines[0] = lines[0][start[1]:]
|
|
content = '\n'.join(lines)
|
|
if hasattr(self, 'replaces'):
|
|
for replace, rstart, rstop in reversed(self.replaces):
|
|
rstart = list(rstart)
|
|
rstop = list(rstop)
|
|
rstart[0] -= start[0]
|
|
rstop[0] -= start[0]
|
|
if rstart[0] == 0:
|
|
rstart[1] -= start[1]
|
|
pass
|
|
if rstop[0] == 0:
|
|
rstop[1] -= start[1]
|
|
pass
|
|
content = replace_text(content, replace, rstart, rstop)
|
|
pass
|
|
pass
|
|
return content
|
|
|
|
def get_pos_end_tag(self):
|
|
pos = self.getpos()
|
|
lines = self.raw_data.split('\n')
|
|
line = lines[pos[0] - 1]
|
|
col = line.find('>', pos[1]) + 1
|
|
return (pos[0], col)
|
|
|
|
def handle_starttag(self, tag, attrs):
|
|
attrs = dict(attrs)
|
|
if tag == 'body':
|
|
self.doc_type = attrs['class'].split()[-1]
|
|
elif tag == 'section' and 'id' in attrs and attrs['id'] == 'main-content':
|
|
if self.doc_type == 'crate':
|
|
self.start_pos = self.getpos()
|
|
elif self.doc_type in ('struct', 'enum', 'union'):
|
|
if not hasattr(self, 'start_pos'):
|
|
self.start_pos = self.getpos()
|
|
pass
|
|
pass
|
|
elif self.doc_type == 'fn':
|
|
if not hasattr(self, 'start_pos'):
|
|
self.start_pos = self.getpos()
|
|
pass
|
|
pass
|
|
pass
|
|
elif 'class' in attrs and 'example-wrap' in attrs['class'].split():
|
|
self.replacing = ' ......<<EXAMPLE>>......<br/>'
|
|
self.replace_depth = 0
|
|
self.replace_start = self.getpos();
|
|
elif 'class' in attrs and 'item-decl' in attrs['class'].split():
|
|
self.replacing = ' ......<<DECLARATION>>......<br/>'
|
|
self.replace_depth = 0
|
|
self.replace_start = self.getpos()
|
|
elif hasattr(self, 'replace_depth'):
|
|
self.replace_depth += 1
|
|
elif hasattr(self, 'depth'):
|
|
self.depth += 1
|
|
pass
|
|
elif hasattr(self, 'start_pos'):
|
|
if self.doc_type in ('struct', 'enum', 'union'):
|
|
if 'id' in attrs and attrs['id'].endswith('implementations'):
|
|
print('%s\n</section>' % self.get_doc_range(self.start_pos, self.getpos()))
|
|
self.doc_type = ''
|
|
pass
|
|
elif self.doc_type == 'fn' and not hasattr(self, 'depth'):
|
|
self.depth = 0
|
|
pass
|
|
elif self.doc_type == 'crate' and 'class' in attrs and attrs['class'].endswith('top-doc'):
|
|
self.depth = 0
|
|
pass
|
|
pass
|
|
pass
|
|
|
|
def handle_endtag(self, tag):
|
|
if hasattr(self, 'replace_depth'):
|
|
if self.replace_depth > 0:
|
|
self.replace_depth -= 1
|
|
else:
|
|
del self.replace_depth
|
|
if not hasattr(self, 'replaces'):
|
|
self.replaces = []
|
|
pass
|
|
self.replaces.append((self.replacing, self.replace_start, self.get_pos_end_tag()))
|
|
pass
|
|
elif hasattr(self, 'depth'):
|
|
if self.depth > 0:
|
|
self.depth -= 1
|
|
pass
|
|
else:
|
|
del self.depth
|
|
if self.doc_type == 'crate':
|
|
content = self.get_doc_range(self.start_pos, self.get_pos_end_tag())
|
|
print('%s\n</section>' % content)
|
|
pass
|
|
elif self.doc_type == 'fn':
|
|
print('%s\n</section>' % self.get_doc_range(self.start_pos, self.get_pos_end_tag()))
|
|
self.doc_type = ''
|
|
pass
|
|
pass
|
|
pass
|
|
pass
|
|
pass
|
|
|
|
|
|
print('<html>')
|
|
print('<head>')
|
|
print('<link rel="preload" as="font" type="font/woff2" crossorigin href="../SourceSerif4-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../FiraSans-Regular.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../FiraSans-Medium.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../SourceCodePro-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../SourceSerif4-Bold.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../SourceCodePro-Semibold.ttf.woff2">')
|
|
print('<link rel="stylesheet" type="text/css" href="../normalize.css"><link rel="stylesheet" type="text/css" href="../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" type="text/css" href="../ayu.css" disabled><link rel="stylesheet" type="text/css" href="../dark.css" disabled><link rel="stylesheet" type="text/css" href="../light.css" id="themeStyle">')
|
|
print('<link rel="stylesheet" href="../noscript.css">')
|
|
print('''<style>
|
|
.tooltip.ignore {
|
|
visibility: hidden;
|
|
}
|
|
.out-of-band {
|
|
visibility: hidden;
|
|
}
|
|
.example-wrap {
|
|
display: block;
|
|
height: 30px;
|
|
overflow: hidden;
|
|
user-select: none;
|
|
}
|
|
.example-wrap::before {
|
|
content: '......<<EXAMPLE>>......';
|
|
}
|
|
.item-decl {
|
|
display: block;
|
|
height: 30px;
|
|
overflow: hidden;
|
|
user-select: none;
|
|
}
|
|
.item-decl::before {
|
|
content: '......<<CODE BLOCK>>......';
|
|
}
|
|
</style>
|
|
''')
|
|
print('</head>')
|
|
print('<body>')
|
|
|
|
for page in pages:
|
|
print('<page filename="%s">' % page)
|
|
p = MyParser()
|
|
fo = open('blazesym/' + page, 'r')
|
|
data = fo.read()
|
|
p.raw_data = data
|
|
p.feed(data)
|
|
print('</page>')
|
|
pass
|
|
|
|
print('</body>')
|
|
print('</html>')
|