diff --git a/cmd/tools/vdoc.v b/cmd/tools/vdoc.v index ad7785fb0b..3c2f08a43c 100644 --- a/cmd/tools/vdoc.v +++ b/cmd/tools/vdoc.v @@ -353,14 +353,15 @@ fn doc_node_html(dd doc.DocNode, link string, head bool, tb &table.Table) string head_tag := if head { 'h1' } else { 'h2' } md_content := markdown.to_html(dd.comment) hlighted_code := html_highlight(dd.content, tb) - is_const_class := if dd.name == 'Constants' { ' const' } else { '' } - mut sym_name := dd.name - if dd.attrs.exists('parent') && dd.attrs['parent'] !in ['void', '', 'Constants'] { - sym_name = dd.attrs['parent'] + '.' + sym_name + node_class := if dd.name == 'Constants' { ' const' } else { '' } + sym_name := if dd.attrs.exists('parent') && dd.attrs['parent'] !in ['void', '', 'Constants'] { + dd.attrs['parent'] + '.' + dd.name + } else { + dd.name } node_id := slug(sym_name) hash_link := if !head { ' #' } else { '' } - dnw.writeln('
') + dnw.writeln('
') if dd.name != 'README' && dd.attrs['parent'] != 'Constants' { dnw.write('
<$head_tag>$sym_name$hash_link') if link.len != 0 { @@ -441,28 +442,22 @@ fn (cfg DocConfig) gen_html(idx int) string { 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 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 if cfg.is_multi || cfg.docs.len > 1 { mut submod_prefix := '' - mut docs := cfg.docs.filter(it.head.name == 'builtin') - docs << cfg.docs.filter(it.head.name != 'builtin') - for i, doc in docs { + for i, doc in cfg.docs { if i-1 >= 0 && doc.head.name.starts_with(submod_prefix + '.') { continue } names := doc.head.name.split('.') submod_prefix = if names.len > 1 { names[0] } else { doc.head.name } - href_name := if doc.head.name == 'README' { + href_name := if ('vlib' in cfg.input_path && doc.head.name == 'builtin' && !cfg.include_readme) || doc.head.name == 'README' { './index.html' } else if submod_prefix !in cfg.docs.map(it.head.name) { '#' - } else if cfg.docs.len == 2 && cfg.readme_idx() == -1 { - './docs.html' } else { './' + doc.head.name + '.html' } @@ -519,16 +514,17 @@ fn (cfg DocConfig) gen_plaintext(idx int) string { dcs := cfg.docs[idx] mut pw := strings.new_builder(200) pw.writeln('${dcs.head.content}\n') - if dcs.head.comment.trim_space().len > 0 { - pw.writeln('// ' + dcs.head.comment.replace('\n', '\n// ') + '\n') + if dcs.head.comment.trim_space().len > 0 && !cfg.pub_only { + pw.writeln(dcs.head.comment.split_into_lines().map(' ' + it).join('\n')) } for cn in dcs.contents { pw.writeln(cn.content) - if cn.comment.len > 0 { - pw.writeln('\/\/ ' + cn.comment.trim_space() + '\n') + if cn.comment.len > 0 && !cfg.pub_only { + pw.writeln(cn.comment.trim_space().split_into_lines().map(' ' + it).join('\n')) } if cfg.show_loc { - pw.writeln('Location: ${cn.file_path}:${cn.pos.line}:${cn.pos.col}\n\n') + pw.writeln('Location: ${cn.file_path}:${cn.pos.line}') + pw.write('\n') } } return pw.str() @@ -560,12 +556,10 @@ fn (cfg DocConfig) render() map[string]string { mut docs := map[string]string for i, doc in cfg.docs { // since builtin is generated first, ignore it - mut name := if doc.head.name == 'README' || cfg.docs.len == 1 { + mut name := if ('vlib' in cfg.input_path && doc.head.name == 'builtin' && !cfg.include_readme) || doc.head.name == 'README' { 'index' } else if !cfg.is_multi && !os.is_dir(cfg.output_path) { os.file_name(cfg.output_path) - } else if i-1 >= 0 && cfg.readme_idx() != -1 && cfg.docs.len == 2 { - 'docs' } else { doc.head.name } @@ -640,8 +634,7 @@ fn (mut cfg DocConfig) generate_docs_from_file() { readme_contents := cfg.get_readme(dir_path) if cfg.output_type == .stdout { println(markdown.to_plain(readme_contents)) - } - if cfg.output_type == .html { + } else if cfg.output_type == .html && cfg.is_multi { cfg.docs << doc.Doc{ head: doc.DocNode{ name: 'README', @@ -651,13 +644,13 @@ fn (mut cfg DocConfig) generate_docs_from_file() { } } } - dirs := if cfg.is_multi { get_modules_list(cfg.input_path) } else { [cfg.input_path] } + dirs := if cfg.is_multi { get_modules_list(cfg.input_path, []string{}) } else { [cfg.input_path] } for dirpath in dirs { cfg.vprintln('Generating docs for ${dirpath}...') mut dcs := doc.generate(dirpath, cfg.pub_only, true) or { mut err_msg := err if errcode == 1 { - mod_list := get_modules_list(cfg.input_path) + mod_list := get_modules_list(cfg.input_path, []string{}) println('Available modules:\n==================') for mod in mod_list { println(mod.all_after('vlib/').all_after('modules/').replace('/', '.')) @@ -668,7 +661,7 @@ fn (mut cfg DocConfig) generate_docs_from_file() { exit(1) } if dcs.contents.len == 0 { continue } - if cfg.is_multi { + if cfg.is_multi || (!cfg.is_multi && cfg.include_readme) { readme_contents := cfg.get_readme(dirpath) dcs.head.comment = readme_contents } @@ -679,6 +672,11 @@ fn (mut cfg DocConfig) generate_docs_from_file() { } cfg.docs << dcs } + if 'vlib' in cfg.input_path { + mut docs := cfg.docs.filter(it.head.name == 'builtin') + docs << cfg.docs.filter(it.head.name != 'builtin') + cfg.docs = docs + } if cfg.serve_http { cfg.serve_html() return @@ -749,6 +747,30 @@ fn (cfg DocConfig) vprintln(str string) { } } +fn get_ignore_paths(path string) ?[]string { + ignore_file_path := os.join_path(path, '.vdocignore') + ignore_content := os.read_file(ignore_file_path) or { + return error_with_code('ignore file not found.', 1) + } + if ignore_content.trim_space().len > 0 { + rules := ignore_content.split_into_lines().map(it.trim_space()) + mut final := []string{} + for rule in rules { + if rule.contains('*.') || rule.contains('**') { + println('vdoc: Wildcards in ignore rules are not allowed for now.') + continue + } + final << rule + } + return final.map(os.join_path(path, it.trim_right('/'))) + } else { + mut dirs := os.ls(path) or { + return []string{} + } + return dirs.map(os.join_path(path, it)).filter(os.is_dir(it)) + } +} + fn lookup_module(mod string) ?string { mod_path := mod.replace('.', os.path_separator) compile_dir := os.real_path(os.base_dir('.')) @@ -763,14 +785,30 @@ fn lookup_module(mod string) ?string { return error('vdoc: Module "${mod}" not found.') } -fn get_modules_list(path string) []string { - files := os.walk_ext(path, 'v') +fn is_included(path string, ignore_paths []string) bool { + if path.len == 0 { + return true + } + for ignore_path in ignore_paths { + if ignore_path !in path { continue } + return false + } + return true +} + +fn get_modules_list(path string, ignore_paths2 []string) []string { + files := os.ls(path) or { return []string{} } + mut ignore_paths := get_ignore_paths(path) or { []string{} } + ignore_paths << ignore_paths2 mut dirs := []string{} for file in files { - 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) - if dirname in dirs { continue } - dirs << dirname + fpath := os.join_path(path, file) + if os.is_dir(fpath) && is_included(fpath, ignore_paths) && !os.is_link(path) { + dirs << get_modules_list(fpath, ignore_paths.filter(it.starts_with(fpath))) + } else if fpath.ends_with('.v') && !fpath.ends_with('_test.v') { + if path in dirs { continue } + dirs << path + } } dirs.sort() return dirs @@ -780,7 +818,11 @@ fn (cfg DocConfig) get_resource(name string, minify bool) string { path := os.join_path(res_path, name) mut res := os.read_file(path) or { panic('could not read $path') } if minify { - res = if name.ends_with('.js') { js_compress(res) } else { res.replace('\n', ' ') } + if name.ends_with('.js') { + res = js_compress(res) + } else { + res = res.split_into_lines().map(it.trim_space()).join('') + } } // TODO: Make SVG inline for now if cfg.inline_assets || path.ends_with('.svg') { diff --git a/cmd/v/help/doc.txt b/cmd/v/help/doc.txt index 00f1834f1d..21369aaaec 100644 --- a/cmd/v/help/doc.txt +++ b/cmd/v/help/doc.txt @@ -13,13 +13,17 @@ or Markdown format. Options: -all Includes private and public functions/methods/structs/consts/enums. -f Specifies the output format to be used. - -inline-assets Embeds the contents of the CSS and JS assets into the webpage directly. - -l Show the locations of the generated signatures. (For plaintext only) + -h, -help Prints this help text. -m Generate docs for modules listed in that folder. -o Specifies the output file/folder path where to store the generated docs. + -readme Include README.md to docs if present. + -v Enables verbose logging. For debugging purposes. + +For HTML mode: + -inline-assets Embeds the contents of the CSS and JS assets into the webpage directly. -open Launches the browser when the server docs has started. -p Specifies the port to be used for the docs server. -s Serve HTML-generated docs via HTTP. - -readme Include README.md to docs if present. - -v Enables verbose logging. For debugging purposes. - -h, -help Prints this help text. \ No newline at end of file + +For plain text mode: + -l Show the locations of the generated signatures. \ No newline at end of file diff --git a/cmd/v/v.v b/cmd/v/v.v index bd21a5d051..a391b74860 100644 --- a/cmd/v/v.v +++ b/cmd/v/v.v @@ -79,7 +79,7 @@ fn main_v() { return } 'vlib-docs' { - util.launch_tool(prefs.is_verbose, 'vdoc', ['doc', '-m', '-s', os.join_path(os.base_dir(@VEXE), 'vlib')]) + util.launch_tool(prefs.is_verbose, 'vdoc', ['doc', 'vlib']) } 'get' { println('V Error: Use `v install` to install modules from vpm.vlang.io') diff --git a/vlib/.vdocignore b/vlib/.vdocignore new file mode 100644 index 0000000000..c43a17047f --- /dev/null +++ b/vlib/.vdocignore @@ -0,0 +1,12 @@ +builtin/bare +builtin/js +oldgg/ +os/bare +os2/ +net/websocket/examples +uiold/ +v/tests/ +v/checker/tests/ +v/gen/js/ +v/gen/x64/ +v/gen/tests/ \ No newline at end of file diff --git a/vlib/os/os.v b/vlib/os/os.v index 61bb4bf298..2e45b6d85f 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -127,6 +127,7 @@ pub fn read_file(path string) ?string { } /***************************** Utility ops ************************/ + pub fn (mut f File) flush() { if !f.opened { return diff --git a/vlib/v/doc/doc.v b/vlib/v/doc/doc.v index 6842b21899..71f13fb969 100644 --- a/vlib/v/doc/doc.v +++ b/vlib/v/doc/doc.v @@ -376,6 +376,9 @@ fn (mut d Doc) generate() ?Doc { } if stmt is ast.FnDecl { fnd := stmt as ast.FnDecl + if fnd.is_deprecated { + continue + } if fnd.receiver.typ != 0 { node.attrs['parent'] = d.fmt.type_to_str(fnd.receiver.typ).trim_left('&') p_idx := d.contents.index_by_name(node.attrs['parent'])