diff --git a/cmd/tools/vdoc/html.v b/cmd/tools/vdoc/html.v index 172bcbae0a..2f0f1fb3e3 100644 --- a/cmd/tools/vdoc/html.v +++ b/cmd/tools/vdoc/html.v @@ -222,14 +222,18 @@ fn (vd &VDoc) gen_html(d doc.Doc) string { if cfg.is_multi || vd.docs.len > 1 { mut used_submod_prefixes := map[string]bool{} for dc in vd.docs { - submod_prefix := dc.head.name.all_before('.') + mut submod_prefix := dc.head.name.all_before('.') + if index := dc.head.frontmatter['index'] { + if dc.head.name == 'index' { + submod_prefix = index + } + } if used_submod_prefixes[submod_prefix] { continue } used_submod_prefixes[submod_prefix] = true mut href_name := './${dc.head.name}.html' - if (cfg.is_vlib && dc.head.name == 'builtin' && !cfg.include_readme) - || dc.head.name == 'README' { + if dc.head.name in ['README', 'index'] { href_name = './index.html' } else if submod_prefix !in vd.docs.map(it.head.name) { href_name = '#' diff --git a/cmd/tools/vdoc/utils.v b/cmd/tools/vdoc/utils.v index f6909a96d0..3b6eafda0b 100644 --- a/cmd/tools/vdoc/utils.v +++ b/cmd/tools/vdoc/utils.v @@ -12,12 +12,15 @@ fn escape(str string) string { } fn get_sym_name(dn doc.DocNode) string { - sym_name := if dn.parent_name.len > 0 && dn.parent_name != 'void' { - '(${dn.parent_name}) ${dn.name}' - } else { - dn.name + if dn.is_readme { + if title := dn.frontmatter['title'] { + return title + } } - return sym_name + if dn.parent_name.len > 0 && dn.parent_name != 'void' { + return '(${dn.parent_name}) ${dn.name}' + } + return dn.name } fn get_node_id(dn doc.DocNode) string { @@ -30,7 +33,7 @@ fn get_node_id(dn doc.DocNode) string { } fn is_module_readme(dn doc.DocNode) bool { - return dn.comments.len > 0 && (dn.content == 'module ${dn.name}' || dn.name == 'README') + return dn.is_readme || (dn.comments.len > 0 && dn.content == 'module ${dn.name}') } // trim_doc_node_description returns the nodes trimmed description. diff --git a/cmd/tools/vdoc/vdoc.v b/cmd/tools/vdoc/vdoc.v index 00386f6e8e..4f7310ae8d 100644 --- a/cmd/tools/vdoc/vdoc.v +++ b/cmd/tools/vdoc/vdoc.v @@ -12,6 +12,11 @@ import v.util import json import term +struct Readme { + frontmatter map[string]string + content string +} + enum OutputType { unset html @@ -159,8 +164,7 @@ fn (mut vd VDoc) render_doc(d doc.Doc, out Output) (string, string) { fn (vd &VDoc) get_file_name(mod string, out Output) string { cfg := vd.cfg mut name := mod - // since builtin is generated first, ignore it - if (cfg.is_vlib && mod == 'builtin' && !cfg.include_readme) || mod == 'README' { + if mod == 'README' { name = 'index' } else if !cfg.is_multi && !os.is_dir(out.path) { name = os.file_name(out.path) @@ -220,10 +224,10 @@ fn (mut vd VDoc) render(out Output) map[string]string { return docs } -fn (vd &VDoc) get_readme(path string) string { +fn (vd &VDoc) get_readme(path string) Readme { mut fname := '' - for name in ['readme', 'README'] { - if os.exists(os.join_path(path, '${name}.md')) { + for name in ['readme.md', 'README.md'] { + if os.exists(os.join_path(path, name)) { fname = name break } @@ -232,12 +236,28 @@ fn (vd &VDoc) get_readme(path string) string { if path.all_after_last(os.path_separator) == 'src' { return vd.get_readme(path.all_before_last(os.path_separator)) } - return '' + return Readme{} } - readme_path := os.join_path(path, '${fname}.md') + readme_path := os.join_path(path, fname) vd.vprintln('Reading README file from ${readme_path}') - readme_contents := os.read_file(readme_path) or { '' } - return readme_contents + mut readme_contents := os.read_file(readme_path) or { '' } + mut readme_frontmatter := map[string]string{} + if readme_contents.starts_with('---\n') { + if frontmatter_lines_end_idx := readme_contents.index('\n---\n') { + front_matter_lines := readme_contents#[4..frontmatter_lines_end_idx].trim_space().split_into_lines() + for line in front_matter_lines { + x := line.split(': ') + if x.len == 2 { + readme_frontmatter[x[0]] = x[1] + } + } + readme_contents = readme_contents#[5 + frontmatter_lines_end_idx..] + } + } + return Readme{ + frontmatter: readme_frontmatter + content: readme_contents + } } fn (vd &VDoc) emit_generate_err(err IError) { @@ -277,7 +297,7 @@ fn (mut vd VDoc) generate_docs_from_file() { exit(1) } dir_path := if cfg.is_vlib { - vroot + os.join_path(vroot, 'vlib') } else if os.is_dir(cfg.input_path) { cfg.input_path } else { @@ -290,18 +310,26 @@ fn (mut vd VDoc) generate_docs_from_file() { vd.manifest = manifest } } - if cfg.include_readme { - readme_contents := vd.get_readme(dir_path) + if cfg.include_readme || cfg.is_vlib { + mut readme_name := 'README' + readme := vd.get_readme(dir_path) + if page := readme.frontmatter['page'] { + readme_name = page + } comment := doc.DocComment{ - text: readme_contents + is_readme: true + frontmatter: readme.frontmatter + text: readme.content } if out.typ == .ansi { - println(markdown.to_plain(readme_contents)) + println(markdown.to_plain(readme.content)) } else if out.typ == .html && cfg.is_multi { vd.docs << doc.Doc{ head: doc.DocNode{ - name: 'README' - comments: [comment] + is_readme: true + name: readme_name + frontmatter: readme.frontmatter + comments: [comment] } time_generated: time.now() } @@ -327,9 +355,11 @@ fn (mut vd VDoc) generate_docs_from_file() { continue } if cfg.is_multi || (!cfg.is_multi && cfg.include_readme) { - readme_contents := vd.get_readme(dirpath) + readme := vd.get_readme(dirpath) comment := doc.DocComment{ - text: readme_contents + is_readme: true + frontmatter: readme.frontmatter + text: readme.content } dcs.head.comments = [comment] } @@ -343,13 +373,6 @@ fn (mut vd VDoc) generate_docs_from_file() { } vd.docs << dcs } - // Important. Let builtin be in the top of the module list - // if we are generating docs for vlib. - if cfg.is_vlib { - mut docs := vd.docs.filter(it.head.name == 'builtin') - docs << vd.docs.filter(it.head.name != 'builtin') - vd.docs = docs - } if dirs.len == 0 && cfg.is_multi { eprintln('vdoc: -m requires at least 1 module folder') exit(1) diff --git a/vlib/README.md b/vlib/README.md index f2f18533a7..19aa64ce7f 100644 --- a/vlib/README.md +++ b/vlib/README.md @@ -1,8 +1,21 @@ -# `vlib` Documentation +--- +page: index +title: V standard library documentation +index: V stdlib +--- +This site contains the documentation for the standard library of modules +included with the [V language](https://vlang.io). Also commonly referred +to as `vlib`, as that is the root directory for these modules in the V +repository. -`vlib` is the term for all modules included by default with V and -maintained as part of the V source code repository. +If you were looking for documentation for the language itself, the +builtin types, operators, et. al., please use the +[V documentation](https://docs.vlang.io/introduction.html) link. Some included modules depend on third party libraries, and these are kept separate in the `thirdparty` directory at the root level of the source repository. + +Note that the [builtin](https://modules.vlang.io/builtin.html) module is +implicitly imported by default in V, so you do not need to have a specific +`import` statement to use any of the features of that module. diff --git a/vlib/v/doc/comment.v b/vlib/v/doc/comment.v index dfb19d024d..99616eac7f 100644 --- a/vlib/v/doc/comment.v +++ b/vlib/v/doc/comment.v @@ -6,9 +6,11 @@ const example_pattern = '\x01 Example: ' pub struct DocComment { pub mut: - text string // Raw text content of the comment, excluding the comment token chars ('//, /*, */') - is_multi bool // Is a block / multi-line comment - pos token.Pos + text string // Raw text content of the comment, excluding the comment token chars ('//, /*, */') + is_multi bool // Is a block / multi-line comment + pos token.Pos + is_readme bool + frontmatter map[string]string } // is_example returns true if the contents of this comment is an inline doc example. diff --git a/vlib/v/doc/doc.v b/vlib/v/doc/doc.v index f236ce1886..5cf27a91b6 100644 --- a/vlib/v/doc/doc.v +++ b/vlib/v/doc/doc.v @@ -143,6 +143,8 @@ pub mut: from_scope bool is_pub bool @[json: public] platform Platform + is_readme bool + frontmatter map[string]string } // new_vdoc_preferences creates a new instance of pref.Preferences tailored for v.doc.