vdoc: fix sorting + other minor improvements
parent
770132ff37
commit
5ff7d07138
|
@ -275,10 +275,10 @@ body {
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
.doc-content > .doc-node.const:not(:first-child) {
|
.doc-content > .doc-node.const:not(:first-child) {
|
||||||
padding-top: 0;
|
padding-top: 4rem;
|
||||||
}
|
}
|
||||||
.doc-content > .doc-node.const:not(:last-child) {
|
.doc-content > .doc-node.const:not(:last-child) {
|
||||||
padding-bottom: 1rem;
|
padding-bottom: 2rem;
|
||||||
}
|
}
|
||||||
.doc-content > .timestamp {
|
.doc-content > .timestamp {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
@ -556,7 +556,12 @@ pre {
|
||||||
.doc-nav .content.hidden {
|
.doc-nav .content.hidden {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
.doc-content > .doc-node.const:not(:first-child) {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
.doc-content > .doc-node.const:not(:last-child) {
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
.doc-container {
|
.doc-container {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-left: 300px;
|
margin-left: 300px;
|
||||||
|
@ -565,7 +570,6 @@ pre {
|
||||||
padding-top: 1rem !important;
|
padding-top: 1rem !important;
|
||||||
margin-top: 0 !important;
|
margin-top: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.doc-toc {
|
.doc-toc {
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
245
cmd/tools/vdoc.v
245
cmd/tools/vdoc.v
|
@ -36,6 +36,51 @@ const (
|
||||||
exe_dir = os.dir(exe_path)
|
exe_dir = os.dir(exe_path)
|
||||||
res_path = os.join_path(exe_dir, 'vdoc-resources')
|
res_path = os.join_path(exe_dir, 'vdoc-resources')
|
||||||
vexe_path = os.base_dir(@VEXE)
|
vexe_path = os.base_dir(@VEXE)
|
||||||
|
html_content = '
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="x-ua-compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{ title }} | vdoc</title>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
{{ head_assets }}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="page">
|
||||||
|
<header class="doc-nav hidden">
|
||||||
|
<div class="heading-container">
|
||||||
|
<div class="heading">
|
||||||
|
<input type="text" id="search" placeholder="Search...">
|
||||||
|
<div class="module">{{ head_name }}</div>
|
||||||
|
<div class="toggle-version-container">
|
||||||
|
<span>{{ version }}</span>
|
||||||
|
<div id="dark-mode-toggle" role="switch" aria-checked="false" aria-label="Toggle dark mode">{{ light_icon }}{{ dark_icon }}</div>
|
||||||
|
</div>
|
||||||
|
{{ menu_icon }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<nav class="content hidden">
|
||||||
|
<ul>
|
||||||
|
{{ toc_links }}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="doc-container">
|
||||||
|
<div class="doc-content">
|
||||||
|
{{ contents }}
|
||||||
|
<div class="footer">
|
||||||
|
{{ footer_content }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ right_content }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ footer_assets }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
'
|
||||||
)
|
)
|
||||||
|
|
||||||
enum OutputType {
|
enum OutputType {
|
||||||
|
@ -92,6 +137,12 @@ fn (mut cfg DocConfig) serve_html() {
|
||||||
if cfg.open_docs {
|
if cfg.open_docs {
|
||||||
open_url(server_url)
|
open_url(server_url)
|
||||||
}
|
}
|
||||||
|
content_type := match cfg.output_type {
|
||||||
|
.html { 'text/html' }
|
||||||
|
.markdown { 'text/markdown' }
|
||||||
|
.json { 'application/json' }
|
||||||
|
else { 'text/plain' }
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
con := server.accept() or {
|
con := server.accept() or {
|
||||||
server.close() or { }
|
server.close() or { }
|
||||||
|
@ -106,7 +157,7 @@ fn (mut cfg DocConfig) serve_html() {
|
||||||
filename = if url.path == '/' { def_name } else { url.path.trim_left('/') }
|
filename = if url.path == '/' { def_name } else { url.path.trim_left('/') }
|
||||||
}
|
}
|
||||||
html := docs[filename]
|
html := docs[filename]
|
||||||
con.write('HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n$html') or {
|
con.write('HTTP/1.1 200 OK\r\nContent-Type: $content_type\r\n\r\n$html') or {
|
||||||
con.close() or { return }
|
con.close() or { return }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -127,9 +178,6 @@ fn get_src_link(repo_url string, file_name string, line_nr int) string {
|
||||||
'git.sir.ht' { '/tree/master/$file_name' }
|
'git.sir.ht' { '/tree/master/$file_name' }
|
||||||
else { '' }
|
else { '' }
|
||||||
}
|
}
|
||||||
if repo_url.starts_with('https://github.com/vlang/v') && !url.path.contains('master/vlib') {
|
|
||||||
url.path = url.path.replace('/blob/master/$file_name', '/blob/master/vlib/$file_name')
|
|
||||||
}
|
|
||||||
if url.path == '/' { return '' }
|
if url.path == '/' { return '' }
|
||||||
url.fragment = 'L$line_nr'
|
url.fragment = 'L$line_nr'
|
||||||
return url.str()
|
return url.str()
|
||||||
|
@ -138,12 +186,12 @@ fn get_src_link(repo_url string, file_name string, line_nr int) string {
|
||||||
fn js_compress(str string) string {
|
fn js_compress(str string) string {
|
||||||
mut js := strings.new_builder(200)
|
mut js := strings.new_builder(200)
|
||||||
lines := str.split_into_lines()
|
lines := str.split_into_lines()
|
||||||
rules := [') {', ' = ', ', ', '{ ', ' }', ' (', '; ', ' + ', ' < ']
|
rules := [') {', ' = ', ', ', '{ ', ' }', ' (', '; ', ' + ', ' < ', ' - ', ' || ', ' var', ': ', ' >= ', ' && ', ' else if', ' === ', ' !== ', ' else ']
|
||||||
clean := ['){', '=', ',', '{', '}', '(', ';', '+', '<']
|
clean := ['){', '=', ',', '{', '}', '(', ';', '+', '<', '-', '||', 'var', ':', '>=', '&&', 'else if', '===', '!==', 'else']
|
||||||
for line in lines {
|
for line in lines {
|
||||||
mut trimmed := line.trim_space()
|
mut trimmed := line.trim_space()
|
||||||
if trimmed.starts_with('//') || (trimmed.starts_with('/*') && trimmed.ends_with('*/')) { continue }
|
if trimmed.starts_with('//') || (trimmed.starts_with('/*') && trimmed.ends_with('*/')) { continue }
|
||||||
for i, _ in rules {
|
for i in 0..rules.len-1 {
|
||||||
trimmed = trimmed.replace(rules[i], clean[i])
|
trimmed = trimmed.replace(rules[i], clean[i])
|
||||||
}
|
}
|
||||||
js.write(trimmed)
|
js.write(trimmed)
|
||||||
|
@ -256,13 +304,13 @@ fn doc_node_html(dd doc.DocNode, link string, head bool, tb &table.Table) string
|
||||||
hlighted_code := html_highlight(dd.content, tb)
|
hlighted_code := html_highlight(dd.content, tb)
|
||||||
is_const_class := if dd.name == 'Constants' { ' const' } else { '' }
|
is_const_class := if dd.name == 'Constants' { ' const' } else { '' }
|
||||||
mut sym_name := dd.name
|
mut sym_name := dd.name
|
||||||
if dd.parent_type !in ['void', '', 'Constants'] {
|
if dd.attrs.exists('parent') && dd.attrs['parent'] !in ['void', '', 'Constants'] {
|
||||||
sym_name = '${dd.parent_type}.' + sym_name
|
sym_name = dd.attrs['parent'] + '.' + sym_name
|
||||||
}
|
}
|
||||||
node_id := slug(sym_name)
|
node_id := slug(sym_name)
|
||||||
hash_link := if !head { ' <a href="#$node_id">#</a>' } else { '' }
|
hash_link := if !head { ' <a href="#$node_id">#</a>' } else { '' }
|
||||||
dnw.writeln('<section id="$node_id" class="doc-node$is_const_class">')
|
dnw.writeln('<section id="$node_id" class="doc-node$is_const_class">')
|
||||||
if dd.name != 'README' && dd.parent_type != 'Constants' {
|
if dd.name != 'README' && dd.attrs['parent'] != 'Constants' {
|
||||||
dnw.write('<div class="title"><$head_tag>$sym_name$hash_link</$head_tag>')
|
dnw.write('<div class="title"><$head_tag>$sym_name$hash_link</$head_tag>')
|
||||||
if link.len != 0 {
|
if link.len != 0 {
|
||||||
dnw.write('<a class="link" rel="noreferrer" target="_blank" href="$link">$link_svg</a>')
|
dnw.write('<a class="link" rel="noreferrer" target="_blank" href="$link">$link_svg</a>')
|
||||||
|
@ -279,10 +327,19 @@ fn doc_node_html(dd doc.DocNode, link string, head bool, tb &table.Table) string
|
||||||
return dnw.str()
|
return dnw.str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (cfg DocConfig) readme_idx() int {
|
||||||
|
for i, dc in cfg.docs {
|
||||||
|
if dc.head.name != 'README' { continue }
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
fn write_toc(cn doc.DocNode, nodes []doc.DocNode, toc &strings.Builder) {
|
fn write_toc(cn doc.DocNode, nodes []doc.DocNode, toc &strings.Builder) {
|
||||||
toc.write('<li><a href="#${slug(cn.name)}">${cn.name}</a>')
|
toc_slug := if cn.content.len == 0 { '' } else { slug(cn.name) }
|
||||||
|
toc.write('<li class="open"><a href="#$toc_slug">${cn.name}</a>')
|
||||||
children := nodes.find_children_of(cn.name)
|
children := nodes.find_children_of(cn.name)
|
||||||
if children.len != 0 && cn.name != 'Constants' {
|
if cn.name != 'Constants' {
|
||||||
toc.writeln(' <ul>')
|
toc.writeln(' <ul>')
|
||||||
for child in children {
|
for child in children {
|
||||||
cname := cn.name + '.' + child.name
|
cname := cn.name + '.' + child.name
|
||||||
|
@ -295,34 +352,32 @@ fn write_toc(cn doc.DocNode, nodes []doc.DocNode, toc &strings.Builder) {
|
||||||
|
|
||||||
fn (cfg DocConfig) write_content(cn &doc.DocNode, dcs &doc.Doc, hw &strings.Builder) {
|
fn (cfg DocConfig) write_content(cn &doc.DocNode, dcs &doc.Doc, hw &strings.Builder) {
|
||||||
base_dir := os.base_dir(os.real_path(cfg.input_path))
|
base_dir := os.base_dir(os.real_path(cfg.input_path))
|
||||||
file_path_name := cn.file_path.replace('$base_dir/', '')
|
file_path_name := if cfg.is_multi { cn.file_path.replace('$base_dir/', '') } else { os.file_name(cn.file_path) }
|
||||||
src_link := get_src_link(cfg.manifest.repo_url, file_path_name, cn.pos.line)
|
src_link := get_src_link(cfg.manifest.repo_url, file_path_name, cn.pos.line)
|
||||||
children := dcs.contents.find_children_of(cn.name)
|
children := dcs.contents.find_children_of(cn.name)
|
||||||
hw.write(doc_node_html(cn, src_link, false, dcs.table))
|
if cn.content.len != 0 {
|
||||||
if children.len != 0 {
|
hw.write(doc_node_html(cn, src_link, false, dcs.table))
|
||||||
for child in children {
|
}
|
||||||
child_file_path_name := child.file_path.replace('$base_dir/', '')
|
for child in children {
|
||||||
child_src_link := get_src_link(cfg.manifest.repo_url, child_file_path_name, child.pos.line)
|
child_file_path_name := child.file_path.replace('$base_dir/', '')
|
||||||
hw.write(doc_node_html(child, child_src_link, false, dcs.table))
|
child_src_link := get_src_link(cfg.manifest.repo_url, child_file_path_name, child.pos.line)
|
||||||
}
|
hw.write(doc_node_html(child, child_src_link, false, dcs.table))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (cfg DocConfig) gen_html(idx int) string {
|
fn (cfg DocConfig) gen_html(idx int) string {
|
||||||
dcs := cfg.docs[idx]
|
dcs := cfg.docs[idx]
|
||||||
time_gen := '$dcs.time_generated.day $dcs.time_generated.smonth() $dcs.time_generated.year $dcs.time_generated.hhmmss()'
|
time_gen := '$dcs.time_generated.day $dcs.time_generated.smonth() $dcs.time_generated.year $dcs.time_generated.hhmmss()'
|
||||||
mut hw := strings.new_builder(200)
|
|
||||||
mut toc := strings.new_builder(200)
|
mut toc := strings.new_builder(200)
|
||||||
|
mut toc2 := strings.new_builder(200)
|
||||||
|
mut contents := strings.new_builder(200)
|
||||||
// generate toc first
|
// generate toc first
|
||||||
const_node_idx := dcs.contents.index_by_name('Constants') or { -1 }
|
contents.writeln(doc_node_html(dcs.head, '', true, dcs.table))
|
||||||
if const_node_idx != -1 {
|
|
||||||
write_toc(dcs.contents[const_node_idx], dcs.contents, &toc)
|
|
||||||
}
|
|
||||||
for cn in dcs.contents {
|
for cn in dcs.contents {
|
||||||
if cn.name == 'Constants' || cn.parent_type !in ['void', ''] { continue }
|
cfg.write_content(&cn, &dcs, &contents)
|
||||||
|
if cn.attrs['parent'] == 'Constants' || cn.attrs['category'] == 'Methods' { continue }
|
||||||
write_toc(cn, dcs.contents, &toc)
|
write_toc(cn, dcs.contents, &toc)
|
||||||
} // write head
|
} // write head
|
||||||
|
|
||||||
// get resources
|
// get resources
|
||||||
doc_css := cfg.get_resource(css_js_assets[0], true)
|
doc_css := cfg.get_resource(css_js_assets[0], true)
|
||||||
normalize_css := cfg.get_resource(css_js_assets[1], true)
|
normalize_css := cfg.get_resource(css_js_assets[1], true)
|
||||||
|
@ -331,47 +386,17 @@ fn (cfg DocConfig) gen_html(idx int) string {
|
||||||
dark_icon := cfg.get_resource('dark.svg', true)
|
dark_icon := cfg.get_resource('dark.svg', true)
|
||||||
menu_icon := cfg.get_resource('menu.svg', true)
|
menu_icon := cfg.get_resource('menu.svg', true)
|
||||||
arrow_icon := cfg.get_resource('arrow.svg', true)
|
arrow_icon := cfg.get_resource('arrow.svg', true)
|
||||||
|
|
||||||
hw.write('
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta http-equiv="x-ua-compatible" content="IE=edge" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>${dcs.head.name} | vdoc</title>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">')
|
|
||||||
|
|
||||||
// write css
|
// write css
|
||||||
if cfg.inline_assets {
|
|
||||||
hw.write('\n <style>$doc_css</style>')
|
|
||||||
hw.write('\n <style>$normalize_css</style>')
|
|
||||||
} else {
|
|
||||||
hw.write('\n <link rel="stylesheet" href="$doc_css" />')
|
|
||||||
hw.write('\n <link rel="stylesheet" href="$normalize_css" />')
|
|
||||||
}
|
|
||||||
|
|
||||||
version := if cfg.manifest.version.len != 0 { cfg.manifest.version } else { '' }
|
version := if cfg.manifest.version.len != 0 { cfg.manifest.version } else { '' }
|
||||||
header_name := if cfg.is_multi && cfg.docs.len > 1 { os.file_name(os.real_path(cfg.input_path)) } else { dcs.head.name }
|
header_name := if cfg.is_multi && cfg.docs.len > 1 {
|
||||||
|
os.file_name(os.real_path(cfg.input_path))
|
||||||
|
} else if cfg.docs.len == 2 && idx+1 < cfg.docs.len && cfg.readme_idx() != -1 {
|
||||||
|
cfg.docs[cfg.readme_idx()+1].head.name
|
||||||
|
} else {
|
||||||
|
dcs.head.name
|
||||||
|
}
|
||||||
// write nav1
|
// write nav1
|
||||||
hw.write('
|
if cfg.is_multi || cfg.docs.len > 1 {
|
||||||
<body>
|
|
||||||
<div id="page">
|
|
||||||
<header class="doc-nav hidden">
|
|
||||||
<div class="heading-container">
|
|
||||||
<div class="heading">
|
|
||||||
<input type="text" id="search" placeholder="Search...">
|
|
||||||
<div class="module">${header_name}</div>
|
|
||||||
<div class="toggle-version-container">
|
|
||||||
<span>${version}</span>
|
|
||||||
<div id="dark-mode-toggle" role="switch" aria-checked="false" aria-label="Toggle dark mode">$light_icon $dark_icon</div>
|
|
||||||
</div>
|
|
||||||
$menu_icon
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<nav class="content hidden">
|
|
||||||
<ul>')
|
|
||||||
if cfg.is_multi && cfg.docs.len > 1 {
|
|
||||||
mut submod_prefix := ''
|
mut submod_prefix := ''
|
||||||
mut docs := cfg.docs.filter(it.head.name == 'builtin')
|
mut docs := cfg.docs.filter(it.head.name == 'builtin')
|
||||||
docs << cfg.docs.filter(it.head.name != 'builtin')
|
docs << cfg.docs.filter(it.head.name != 'builtin')
|
||||||
|
@ -385,6 +410,8 @@ fn (cfg DocConfig) gen_html(idx int) string {
|
||||||
'./index.html'
|
'./index.html'
|
||||||
} else if submod_prefix !in cfg.docs.map(it.head.name) {
|
} else if submod_prefix !in cfg.docs.map(it.head.name) {
|
||||||
'#'
|
'#'
|
||||||
|
} else if cfg.docs.len == 2 && cfg.readme_idx() == -1 {
|
||||||
|
'./docs.html'
|
||||||
} else {
|
} else {
|
||||||
'./' + doc.head.name + '.html'
|
'./' + doc.head.name + '.html'
|
||||||
}
|
}
|
||||||
|
@ -397,46 +424,44 @@ fn (cfg DocConfig) gen_html(idx int) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
active_class := if doc.head.name == dcs.head.name { ' active' } else { '' }
|
active_class := if doc.head.name == dcs.head.name { ' active' } else { '' }
|
||||||
hw.write('<li class="open$active_class"><div class="menu-row">$dropdown<a href="$href_name">${submod_prefix}</a></div>')
|
toc2.write('<li class="open$active_class"><div class="menu-row">$dropdown<a href="$href_name">${submod_prefix}</a></div>')
|
||||||
for j, cdoc in submodules {
|
for j, cdoc in submodules {
|
||||||
if j == 0 {
|
if j == 0 {
|
||||||
hw.write('<ul>')
|
toc2.write('<ul>')
|
||||||
}
|
}
|
||||||
submod_name := cdoc.head.name.all_after(submod_prefix + '.')
|
submod_name := cdoc.head.name.all_after(submod_prefix + '.')
|
||||||
sub_selected_classes := if cdoc.head.name == dcs.head.name { ' class="active"' } else { '' }
|
sub_selected_classes := if cdoc.head.name == dcs.head.name { ' class="active"' } else { '' }
|
||||||
hw.write('<li$sub_selected_classes><a href="./${cdoc.head.name}.html">${submod_name}</a></li>')
|
toc2.write('<li$sub_selected_classes><a href="./${cdoc.head.name}.html">${submod_name}</a></li>')
|
||||||
if j == submodules.len - 1 {
|
if j == submodules.len - 1 {
|
||||||
hw.write('</ul>')
|
toc2.write('</ul>')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hw.write('</li>')
|
toc2.write('</li>')
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
hw.writeln(toc.str())
|
|
||||||
}
|
}
|
||||||
hw.write('</ul>\n</nav>\n</header>')
|
return html_content
|
||||||
hw.write('<div class="doc-container">\n<div class="doc-content">\n')
|
.replace('{{ title }}', dcs.head.name)
|
||||||
hw.write(doc_node_html(dcs.head, '', true, dcs.table))
|
.replace('{{ head_name }}', header_name)
|
||||||
if const_node_idx != -1 {
|
.replace('{{ version }}', version)
|
||||||
cfg.write_content(&dcs.contents[const_node_idx], &dcs, &hw)
|
.replace('{{ light_icon }}', light_icon)
|
||||||
}
|
.replace('{{ dark_icon }}', dark_icon)
|
||||||
for cn in dcs.contents {
|
.replace('{{ menu_icon }}', menu_icon)
|
||||||
if cn.parent_type !in ['void', ''] || cn.name == 'Constants' { continue }
|
.replace('{{ head_assets }}', if cfg.inline_assets {
|
||||||
cfg.write_content(&cn, &dcs, &hw)
|
'\n <style>$doc_css</style>\n <style>$normalize_css</style>'
|
||||||
}
|
} else {
|
||||||
hw.write('\n<div class="footer">Powered by vdoc. Generated on: $time_gen</div>\n</div>\n')
|
'\n <link rel="stylesheet" href="$doc_css" />\n <link rel="stylesheet" href="$normalize_css" />'
|
||||||
if cfg.is_multi && cfg.docs.len > 1 && dcs.head.name != 'README' {
|
})
|
||||||
hw.write('<div class="doc-toc">\n\n<ul>\n${toc.str()}</ul>\n</div>')
|
.replace('{{ toc_links }}', if cfg.is_multi || cfg.docs.len > 1 { toc2.str() } else { toc.str() })
|
||||||
}
|
.replace('{{ contents }}', contents.str())
|
||||||
hw.write('</div></div>')
|
.replace('{{ right_content }}', if cfg.is_multi && cfg.docs.len > 1 && dcs.head.name != 'README' {
|
||||||
if cfg.inline_assets {
|
'<div class="doc-toc"><ul>' + toc.str() + '</ul></div>'
|
||||||
hw.write('<script>$doc_js</script>')
|
} else { '' })
|
||||||
} else {
|
.replace('{{ footer_content }}', 'Powered by vdoc. Generated on: $time_gen')
|
||||||
hw.write('<script src="$doc_js"></script>')
|
.replace('{{ footer_assets }}', if cfg.inline_assets {
|
||||||
}
|
'<script>$doc_js</script>'
|
||||||
hw.write('</body>
|
} else {
|
||||||
</html>')
|
'<script src="$doc_js"></script>'
|
||||||
return hw.str()
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (cfg DocConfig) gen_plaintext(idx int) string {
|
fn (cfg DocConfig) gen_plaintext(idx int) string {
|
||||||
|
@ -482,13 +507,14 @@ fn (cfg DocConfig) gen_markdown(idx int, with_toc bool) string {
|
||||||
|
|
||||||
fn (cfg DocConfig) render() map[string]string {
|
fn (cfg DocConfig) render() map[string]string {
|
||||||
mut docs := map[string]string
|
mut docs := map[string]string
|
||||||
|
|
||||||
for i, doc in cfg.docs {
|
for i, doc in cfg.docs {
|
||||||
// since builtin is generated first, ignore it
|
// since builtin is generated first, ignore it
|
||||||
mut name := if doc.head.name == 'README' {
|
mut name := if doc.head.name == 'README' || cfg.docs.len == 1 {
|
||||||
'index'
|
'index'
|
||||||
} else if !cfg.is_multi && !os.is_dir(cfg.output_path) {
|
} else if !cfg.is_multi && !os.is_dir(cfg.output_path) {
|
||||||
os.file_name(cfg.output_path)
|
os.file_name(cfg.output_path)
|
||||||
|
} else if i-1 >= 0 && cfg.readme_idx() != -1 && cfg.docs.len == 2 {
|
||||||
|
'docs'
|
||||||
} else {
|
} else {
|
||||||
doc.head.name
|
doc.head.name
|
||||||
}
|
}
|
||||||
|
@ -579,7 +605,12 @@ fn (mut cfg DocConfig) generate_docs_from_file() {
|
||||||
mut dcs := doc.generate(dirpath, cfg.pub_only, true) or {
|
mut dcs := doc.generate(dirpath, cfg.pub_only, true) or {
|
||||||
mut err_msg := err
|
mut err_msg := err
|
||||||
if errcode == 1 {
|
if errcode == 1 {
|
||||||
err_msg += ' Use the `-m` flag if you are generating docs of a directory with multiple modules inside.'
|
mod_list := get_modules_list(cfg.input_path)
|
||||||
|
println('Available modules:\n==================')
|
||||||
|
for mod in mod_list {
|
||||||
|
println(mod.all_after('vlib/').all_after('modules/').replace('/', '.'))
|
||||||
|
}
|
||||||
|
err_msg += ' Use the `-m` flag if you are generating docs of a directory containing multiple modules.'
|
||||||
}
|
}
|
||||||
eprintln(err_msg)
|
eprintln(err_msg)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
@ -613,6 +644,11 @@ fn (mut cfg DocConfig) generate_docs_from_file() {
|
||||||
if !os.is_dir(cfg.output_path) {
|
if !os.is_dir(cfg.output_path) {
|
||||||
cfg.output_path = os.real_path('.')
|
cfg.output_path = os.real_path('.')
|
||||||
}
|
}
|
||||||
|
if !os.exists(cfg.output_path) {
|
||||||
|
os.mkdir(cfg.output_path) or {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
if cfg.is_multi {
|
if cfg.is_multi {
|
||||||
cfg.output_path = os.join_path(cfg.output_path, '_docs')
|
cfg.output_path = os.join_path(cfg.output_path, '_docs')
|
||||||
if !os.exists(cfg.output_path) {
|
if !os.exists(cfg.output_path) {
|
||||||
|
@ -679,7 +715,7 @@ fn get_modules_list(path string) []string {
|
||||||
files := os.walk_ext(path, 'v')
|
files := os.walk_ext(path, 'v')
|
||||||
mut dirs := []string{}
|
mut dirs := []string{}
|
||||||
for file in files {
|
for file in files {
|
||||||
if 'test' in file || 'js' in file || 'x64' in file || 'bare' in file || 'uiold' in file || 'vweb' in file { continue }
|
if 'vlib' in path && ('examples' in file || 'test' in file || 'js' in file || 'x64' in file || 'bare' in file || 'uiold' in file || 'vweb' in file) { continue }
|
||||||
dirname := os.base_dir(file)
|
dirname := os.base_dir(file)
|
||||||
if dirname in dirs { continue }
|
if dirname in dirs { continue }
|
||||||
dirs << dirname
|
dirs << dirname
|
||||||
|
@ -766,9 +802,11 @@ fn main() {
|
||||||
'-s' {
|
'-s' {
|
||||||
cfg.inline_assets = true
|
cfg.inline_assets = true
|
||||||
cfg.serve_http = true
|
cfg.serve_http = true
|
||||||
cfg.output_type = .html
|
if cfg.output_type == .unset {
|
||||||
|
cfg.output_type = .html
|
||||||
|
}
|
||||||
}
|
}
|
||||||
'-r' {
|
'-readme' {
|
||||||
cfg.include_readme = true
|
cfg.include_readme = true
|
||||||
}
|
}
|
||||||
'-v' {
|
'-v' {
|
||||||
|
@ -784,6 +822,11 @@ fn main() {
|
||||||
eprintln('vdoc: No input path found.')
|
eprintln('vdoc: No input path found.')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
$if windows {
|
||||||
|
cfg.input_path = cfg.input_path.replace('/', os.path_separator)
|
||||||
|
} $else {
|
||||||
|
cfg.input_path = cfg.input_path.replace('\\', os.path_separator)
|
||||||
|
}
|
||||||
is_path := cfg.input_path.ends_with('.v') || cfg.input_path.split(os.path_separator).len > 1 || cfg.input_path == '.'
|
is_path := cfg.input_path.ends_with('.v') || cfg.input_path.split(os.path_separator).len > 1 || cfg.input_path == '.'
|
||||||
if cfg.input_path == 'vlib' {
|
if cfg.input_path == 'vlib' {
|
||||||
cfg.is_multi = true
|
cfg.is_multi = true
|
||||||
|
|
|
@ -20,6 +20,6 @@ Options:
|
||||||
-open Launches the browser when the server docs has started.
|
-open Launches the browser when the server docs has started.
|
||||||
-p Specifies the port to be used for the docs server.
|
-p Specifies the port to be used for the docs server.
|
||||||
-s Serve HTML-generated docs via HTTP.
|
-s Serve HTML-generated docs via HTTP.
|
||||||
-r Include README.md to docs if present.
|
-readme Include README.md to docs if present.
|
||||||
-v Enables verbose logging. For debugging purposes.
|
-v Enables verbose logging. For debugging purposes.
|
||||||
-h, -help Prints this help text.
|
-h, -help Prints this help text.
|
|
@ -123,7 +123,7 @@ pub fn (ftp FTP) login(user, passwd string) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
mut code, mut data := ftp.read()
|
mut code, _ := ftp.read()
|
||||||
if code == logged_in {
|
if code == logged_in {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,11 @@ import picohttpparser
|
||||||
#include "src/picoev.h"
|
#include "src/picoev.h"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MAX_FDS = 1024
|
max_fds = 1024
|
||||||
TIMEOUT_SECS = 8
|
timeout_secs = 8
|
||||||
MAX_TIMEOUT = 10
|
max_timeout = 10
|
||||||
MAX_READ = 4096
|
max_read = 4096
|
||||||
MAX_WRITE = 8192
|
max_write = 8192
|
||||||
)
|
)
|
||||||
|
|
||||||
struct C.in_addr {
|
struct C.in_addr {
|
||||||
|
@ -122,10 +122,10 @@ fn rw_callback(loop &C.picoev_loop, fd, events int, cb_arg voidptr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
else if (events & C.PICOEV_READ) != 0 {
|
else if (events & C.PICOEV_READ) != 0 {
|
||||||
C.picoev_set_timeout(loop, fd, TIMEOUT_SECS)
|
C.picoev_set_timeout(loop, fd, timeout_secs)
|
||||||
buf := (p.buf + fd * MAX_READ)
|
buf := (p.buf + fd * max_read)
|
||||||
idx := p.idx[fd]
|
idx := p.idx[fd]
|
||||||
mut r := myread(fd, buf, MAX_READ, idx)
|
mut r := myread(fd, buf, max_read, idx)
|
||||||
if r == 0 {
|
if r == 0 {
|
||||||
close_conn(loop, fd)
|
close_conn(loop, fd)
|
||||||
p.idx[fd] = 0
|
p.idx[fd] = 0
|
||||||
|
@ -141,7 +141,7 @@ fn rw_callback(loop &C.picoev_loop, fd, events int, cb_arg voidptr) {
|
||||||
} else {
|
} else {
|
||||||
r += idx
|
r += idx
|
||||||
mut s := tos(buf, r)
|
mut s := tos(buf, r)
|
||||||
out := (p.out + fd * MAX_WRITE)
|
out := (p.out + fd * max_write)
|
||||||
mut res := picohttpparser.Response{
|
mut res := picohttpparser.Response{
|
||||||
fd: fd
|
fd: fd
|
||||||
date: p.date
|
date: p.date
|
||||||
|
@ -191,7 +191,7 @@ fn accept_callback(loop &C.picoev_loop, fd, events int, cb_arg voidptr) {
|
||||||
newfd := C.accept(fd, 0, 0)
|
newfd := C.accept(fd, 0, 0)
|
||||||
if newfd != -1 {
|
if newfd != -1 {
|
||||||
setup_sock(newfd)
|
setup_sock(newfd)
|
||||||
C.picoev_add(loop, newfd, C.PICOEV_READ, TIMEOUT_SECS, rw_callback, cb_arg)
|
C.picoev_add(loop, newfd, C.PICOEV_READ, timeout_secs, rw_callback, cb_arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,14 +223,14 @@ pub fn new(port int, cb voidptr) &Picoev {
|
||||||
|
|
||||||
setup_sock(fd)
|
setup_sock(fd)
|
||||||
|
|
||||||
C.picoev_init(MAX_FDS)
|
C.picoev_init(max_fds)
|
||||||
loop := C.picoev_create_loop(MAX_TIMEOUT)
|
loop := C.picoev_create_loop(max_timeout)
|
||||||
pv := &Picoev{
|
pv := &Picoev{
|
||||||
loop: loop
|
loop: loop
|
||||||
cb: cb
|
cb: cb
|
||||||
date: C.get_date()
|
date: C.get_date()
|
||||||
buf: malloc(MAX_FDS * MAX_READ + 1)
|
buf: malloc(max_fds * max_read + 1)
|
||||||
out: malloc(MAX_FDS * MAX_WRITE + 1)
|
out: malloc(max_fds * max_write + 1)
|
||||||
}
|
}
|
||||||
C.picoev_add(loop, fd, C.PICOEV_READ, 0, accept_callback, pv)
|
C.picoev_add(loop, fd, C.PICOEV_READ, 0, accept_callback, pv)
|
||||||
|
|
||||||
|
|
158
vlib/v/doc/doc.v
158
vlib/v/doc/doc.v
|
@ -21,6 +21,7 @@ pub mut:
|
||||||
head DocNode
|
head DocNode
|
||||||
with_comments bool = true
|
with_comments bool = true
|
||||||
contents []DocNode
|
contents []DocNode
|
||||||
|
fmt fmt.Fmt
|
||||||
time_generated time.Time
|
time_generated time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ pub mut:
|
||||||
comment string
|
comment string
|
||||||
pos DocPos = DocPos{-1, -1}
|
pos DocPos = DocPos{-1, -1}
|
||||||
file_path string = ''
|
file_path string = ''
|
||||||
parent_type string = ''
|
attrs map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn merge_comments(stmts []ast.Stmt) string {
|
pub fn merge_comments(stmts []ast.Stmt) string {
|
||||||
|
@ -112,65 +113,55 @@ fn convert_pos(file_path string, pos token.Position) DocPos {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (d Doc) get_signature(stmt ast.Stmt, file &ast.File) string {
|
pub fn (mut d Doc) get_signature(stmt ast.Stmt, file &ast.File) string {
|
||||||
mut f := fmt.Fmt{
|
|
||||||
out: strings.new_builder(1000)
|
|
||||||
out_imports: strings.new_builder(200)
|
|
||||||
table: d.table
|
|
||||||
file: file
|
|
||||||
cur_mod: d.head.name.split('.').last()
|
|
||||||
indent: 0
|
|
||||||
is_debug: false
|
|
||||||
}
|
|
||||||
f.process_file_imports(file)
|
|
||||||
match stmt {
|
match stmt {
|
||||||
ast.Module {
|
ast.Module {
|
||||||
return 'module $it.name'
|
return 'module $stmt.name'
|
||||||
}
|
}
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
return it.str(d.table).replace(f.cur_mod + '.', '')
|
return stmt.str(d.table).replace(d.fmt.cur_mod + '.', '')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
f.stmt(stmt)
|
d.fmt.out = strings.new_builder(1000)
|
||||||
return f.out.str().trim_space()
|
d.fmt.stmt(stmt)
|
||||||
|
return d.fmt.out.str().trim_space()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (d Doc) get_pos(stmt ast.Stmt) token.Position {
|
pub fn (d Doc) get_pos(stmt ast.Stmt) token.Position {
|
||||||
match stmt {
|
match stmt {
|
||||||
ast.FnDecl { return it.pos }
|
ast.FnDecl { return stmt.pos }
|
||||||
ast.StructDecl { return it.pos }
|
ast.StructDecl { return stmt.pos }
|
||||||
ast.EnumDecl { return it.pos }
|
ast.EnumDecl { return stmt.pos }
|
||||||
ast.InterfaceDecl { return it.pos }
|
ast.InterfaceDecl { return stmt.pos }
|
||||||
ast.ConstDecl { return it.pos }
|
ast.ConstDecl { return stmt.pos }
|
||||||
else { return token.Position{} }
|
else { return token.Position{} }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (d Doc) get_type_name(decl ast.TypeDecl) string {
|
pub fn (d Doc) get_type_name(decl ast.TypeDecl) string {
|
||||||
match decl {
|
match decl {
|
||||||
ast.SumTypeDecl { return it.name }
|
ast.SumTypeDecl { return decl.name }
|
||||||
ast.FnTypeDecl { return it.name }
|
ast.FnTypeDecl { return decl.name }
|
||||||
ast.AliasTypeDecl { return it.name }
|
ast.AliasTypeDecl { return decl.name }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (d Doc) get_name(stmt ast.Stmt) string {
|
pub fn (d Doc) get_name(stmt ast.Stmt) string {
|
||||||
cur_mod := d.head.name.split('.').last()
|
|
||||||
match stmt {
|
match stmt {
|
||||||
ast.FnDecl { return it.name }
|
ast.FnDecl { return stmt.name }
|
||||||
ast.StructDecl { return it.name }
|
ast.StructDecl { return stmt.name }
|
||||||
ast.EnumDecl { return it.name }
|
ast.EnumDecl { return stmt.name }
|
||||||
ast.InterfaceDecl { return it.name }
|
ast.InterfaceDecl { return stmt.name }
|
||||||
ast.TypeDecl { return d.get_type_name(it).replace('&' + cur_mod + '.', '').replace(cur_mod + '.', '') }
|
ast.TypeDecl { return d.get_type_name(stmt) }
|
||||||
ast.ConstDecl { return 'Constants' }
|
ast.ConstDecl { return 'Constants' }
|
||||||
else { return '' }
|
else { return '' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(input_path string) Doc {
|
pub fn new(input_path string) Doc {
|
||||||
return Doc{
|
mut d := Doc{
|
||||||
input_path: os.real_path(input_path)
|
input_path: os.real_path(input_path)
|
||||||
prefs: &pref.Preferences{}
|
prefs: &pref.Preferences{}
|
||||||
table: table.new_table()
|
table: table.new_table()
|
||||||
|
@ -178,28 +169,59 @@ pub fn new(input_path string) Doc {
|
||||||
contents: []DocNode{}
|
contents: []DocNode{}
|
||||||
time_generated: time.now()
|
time_generated: time.now()
|
||||||
}
|
}
|
||||||
|
d.fmt = fmt.Fmt{
|
||||||
|
indent: 0
|
||||||
|
is_debug: false
|
||||||
|
table: d.table
|
||||||
|
}
|
||||||
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (nodes []DocNode) index_by_name(node_name string) ?int {
|
pub fn (mut nodes []DocNode) sort_by_name() {
|
||||||
|
nodes.sort_with_compare(compare_nodes_by_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut nodes []DocNode) sort_by_category() {
|
||||||
|
nodes.sort_with_compare(compare_nodes_by_category)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_nodes_by_name(a, b &DocNode) int {
|
||||||
|
al := a.name.to_lower()
|
||||||
|
bl := b.name.to_lower()
|
||||||
|
return compare_strings(al, bl)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_nodes_by_category(a, b &DocNode) int {
|
||||||
|
al := a.attrs['category']
|
||||||
|
bl := b.attrs['category']
|
||||||
|
return compare_strings(al, bl)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (nodes []DocNode) index_by_name(node_name string) int {
|
||||||
for i, node in nodes {
|
for i, node in nodes {
|
||||||
if node.name != node_name { continue }
|
if node.name != node_name { continue }
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
return error('Node with the name "$node_name" was not found.')
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (nodes []DocNode) find_children_of(parent_type string) []DocNode {
|
pub fn (nodes []DocNode) find_children_of(parent string) []DocNode {
|
||||||
if parent_type.len == 0 {
|
return nodes.find_nodes_with_attr('parent', parent)
|
||||||
return []DocNode{}
|
}
|
||||||
|
|
||||||
|
pub fn (nodes []DocNode) find_nodes_with_attr(attr_name string, value string) []DocNode {
|
||||||
|
mut subgroup := []DocNode{}
|
||||||
|
if attr_name.len == 0 {
|
||||||
|
return subgroup
|
||||||
}
|
}
|
||||||
mut children := []DocNode{}
|
|
||||||
for node in nodes {
|
for node in nodes {
|
||||||
if node.parent_type != parent_type {
|
if !node.attrs.exists(attr_name) || node.attrs[attr_name] != value {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
children << node
|
subgroup << node
|
||||||
}
|
}
|
||||||
return children
|
subgroup.sort_by_name()
|
||||||
|
return subgroup
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_parent_mod(dir string) ?string {
|
fn get_parent_mod(dir string) ?string {
|
||||||
|
@ -242,7 +264,7 @@ fn get_parent_mod(dir string) ?string {
|
||||||
return file_ast.mod.name
|
return file_ast.mod.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut d Doc) generate() ?bool {
|
fn (mut d Doc) generate() ?Doc {
|
||||||
// get all files
|
// get all files
|
||||||
base_path := if os.is_dir(d.input_path) { d.input_path } else { os.real_path(os.base_dir(d.input_path)) }
|
base_path := if os.is_dir(d.input_path) { d.input_path } else { os.real_path(os.base_dir(d.input_path)) }
|
||||||
project_files := os.ls(base_path) or {
|
project_files := os.ls(base_path) or {
|
||||||
|
@ -285,7 +307,9 @@ pub fn (mut d Doc) generate() ?bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stmts := file_ast.stmts
|
stmts := file_ast.stmts
|
||||||
//
|
d.fmt.file = file_ast
|
||||||
|
d.fmt.cur_mod = orig_mod_name
|
||||||
|
d.fmt.process_file_imports(file_ast)
|
||||||
mut last_import_stmt_idx := 0
|
mut last_import_stmt_idx := 0
|
||||||
for sidx, stmt in stmts {
|
for sidx, stmt in stmts {
|
||||||
if stmt is ast.Import {
|
if stmt is ast.Import {
|
||||||
|
@ -306,10 +330,7 @@ pub fn (mut d Doc) generate() ?bool {
|
||||||
module_comment := get_comment_block_right_before(prev_comments)
|
module_comment := get_comment_block_right_before(prev_comments)
|
||||||
prev_comments = []
|
prev_comments = []
|
||||||
if 'vlib' !in base_path && !module_comment.starts_with('Copyright (c)') {
|
if 'vlib' !in base_path && !module_comment.starts_with('Copyright (c)') {
|
||||||
if module_comment == '' {
|
if module_comment in ['', d.head.comment] {
|
||||||
continue
|
|
||||||
}
|
|
||||||
if module_comment == d.head.comment {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if d.head.comment != '' {
|
if d.head.comment != '' {
|
||||||
|
@ -350,25 +371,45 @@ pub fn (mut d Doc) generate() ?bool {
|
||||||
pos: convert_pos(v_files[i], pos)
|
pos: convert_pos(v_files[i], pos)
|
||||||
file_path: v_files[i]
|
file_path: v_files[i]
|
||||||
}
|
}
|
||||||
|
if node.name.len == 0 && node.comment.len == 0 && node.content.len == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if stmt is ast.FnDecl {
|
if stmt is ast.FnDecl {
|
||||||
fnd := stmt as ast.FnDecl
|
fnd := stmt as ast.FnDecl
|
||||||
if fnd.receiver.typ != 0 {
|
if fnd.receiver.typ != 0 {
|
||||||
mut parent_type := d.table.get_type_name(fnd.receiver.typ)
|
node.attrs['parent'] = d.fmt.type_to_str(fnd.receiver.typ).trim_left('&')
|
||||||
if parent_type.starts_with(module_name + '.') {
|
p_idx := d.contents.index_by_name(node.attrs['parent'])
|
||||||
parent_type = parent_type.all_after(module_name + '.')
|
if p_idx == -1 && node.attrs['parent'] != 'void' {
|
||||||
|
d.contents << DocNode{
|
||||||
|
name: node.attrs['parent']
|
||||||
|
content: ''
|
||||||
|
comment: ''
|
||||||
|
attrs: {'category': 'Structs'}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
node.parent_type = parent_type
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if stmt is ast.ConstDecl {
|
if stmt is ast.ConstDecl {
|
||||||
if const_idx == -1 {
|
if const_idx == -1 {
|
||||||
const_idx = sidx
|
const_idx = sidx
|
||||||
} else {
|
} else {
|
||||||
node.parent_type = 'Constants'
|
node.attrs['parent'] = 'Constants'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if node.name.len == 0 && node.comment.len == 0 && node.content.len == 0 {
|
match stmt {
|
||||||
continue
|
ast.ConstDecl { node.attrs['category'] = 'Constants' }
|
||||||
|
ast.EnumDecl { node.attrs['category'] = 'Enums' }
|
||||||
|
ast.InterfaceDecl { node.attrs['category'] = 'Interfaces' }
|
||||||
|
ast.StructDecl { node.attrs['category'] = 'Structs' }
|
||||||
|
ast.TypeDecl { node.attrs['category'] = 'Typedefs' }
|
||||||
|
ast.FnDecl {
|
||||||
|
node.attrs['category'] = if node.attrs['parent'] in ['void', ''] || !node.attrs.exists('parent') {
|
||||||
|
'Functions'
|
||||||
|
} else {
|
||||||
|
'Methods'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
}
|
}
|
||||||
d.contents << node
|
d.contents << node
|
||||||
if d.with_comments && (prev_comments.len > 0) {
|
if d.with_comments && (prev_comments.len > 0) {
|
||||||
|
@ -378,17 +419,18 @@ pub fn (mut d Doc) generate() ?bool {
|
||||||
}
|
}
|
||||||
prev_comments = []
|
prev_comments = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.fmt.mod2alias = map[string]string{}
|
||||||
}
|
}
|
||||||
d.time_generated = time.now()
|
d.time_generated = time.now()
|
||||||
return true
|
d.contents.sort_by_name()
|
||||||
|
d.contents.sort_by_category()
|
||||||
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate(input_path string, pub_only, with_comments bool) ?Doc {
|
pub fn generate(input_path string, pub_only, with_comments bool) ?Doc {
|
||||||
mut doc := new(input_path)
|
mut doc := new(input_path)
|
||||||
doc.pub_only = pub_only
|
doc.pub_only = pub_only
|
||||||
doc.with_comments = with_comments
|
doc.with_comments = with_comments
|
||||||
doc.generate() or {
|
return doc.generate()
|
||||||
return error_with_code(err, errcode)
|
|
||||||
}
|
|
||||||
return doc
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -514,7 +514,7 @@ pub fn (mut f Fmt) struct_field_expr(fexpr ast.Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (f &Fmt) type_to_str(t table.Type) string {
|
pub fn (f &Fmt) type_to_str(t table.Type) string {
|
||||||
mut res := f.table.type_to_str(t)
|
mut res := f.table.type_to_str(t)
|
||||||
for res.ends_with('_ptr') {
|
for res.ends_with('_ptr') {
|
||||||
// type_ptr => &type
|
// type_ptr => &type
|
||||||
|
|
|
@ -282,6 +282,7 @@ fn os_from_string(os string) pref.OS {
|
||||||
|
|
||||||
// Helper function to convert string names to CC enum
|
// Helper function to convert string names to CC enum
|
||||||
pub fn cc_from_string(cc_str string) pref.CompilerType {
|
pub fn cc_from_string(cc_str string) pref.CompilerType {
|
||||||
|
if cc_str.len == 0 { return .gcc }
|
||||||
cc := cc_str.replace('\\', '/').split('/').last().all_before('.')
|
cc := cc_str.replace('\\', '/').split('/').last().all_before('.')
|
||||||
if 'tcc' in cc { return .tinyc }
|
if 'tcc' in cc { return .tinyc }
|
||||||
if 'tinyc' in cc { return .tinyc }
|
if 'tinyc' in cc { return .tinyc }
|
||||||
|
|
Loading…
Reference in New Issue