diff --git a/cmd/tools/vdoc-resources/arrow.svg b/cmd/tools/vdoc-resources/arrow.svg
new file mode 100644
index 0000000000..2a0456fad1
--- /dev/null
+++ b/cmd/tools/vdoc-resources/arrow.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/cmd/tools/vdoc-resources/dark.svg b/cmd/tools/vdoc-resources/dark.svg
new file mode 100644
index 0000000000..2067d05b94
--- /dev/null
+++ b/cmd/tools/vdoc-resources/dark.svg
@@ -0,0 +1 @@
+
diff --git a/cmd/tools/vdoc-resources/doc.css b/cmd/tools/vdoc-resources/doc.css
new file mode 100644
index 0000000000..94847183aa
--- /dev/null
+++ b/cmd/tools/vdoc-resources/doc.css
@@ -0,0 +1,443 @@
+:root {
+ --background-color: #fff;
+ --timestamp-color: #b8c2cc;
+ --link-color: #2779bd;
+ --font-color: #000;
+ --ref-symbol-color: #dae1e7;
+ --ref-symbol-hover-color: #b8c2cc;
+ --title-bottom-line-color: #f1f5f8;
+ --code-background-color: #edf2f7;
+ --code-signature-border-color: #a0aec0;
+ --menu-background-color: #4b6c88;
+ --menu-font-color: #fff;
+ --menu-indent-line-color: #ffffff66;
+ --menu-indent-line-active-color: #00000066;
+ --menu-scrollbar-color: #a0aec0;
+ --menu-toggle-icon-color: #fff;
+ --menu-toggle-icon-hover-color: #00000044;
+ --menu-search-background-color: #00000044;
+ --menu-search-font-color: #fff;
+ --toc-font-color: #2779bd;
+ --toc-indent-line-color: #dae1e7;
+}
+:root.dark .dark-icon {
+ display: none;
+}
+:root:not(.dark) .light-icon {
+ display: none;
+}
+
+body {
+ font-family: 'Inter', sans-serif;
+ background-color: #fff;
+ background-color: var(--background-color);
+ color: #000;
+ color: var(--font-color);
+}
+
+.dark body {
+ --background-color: #1a202c;
+ --timestamp-color: #b8c2cc;
+ --font-color: #fff;
+ --link-color: #90cdf4;
+ --ref-symbol-color: #2d3748;
+ --ref-symbol-hover-color: #4a5568;
+ --title-bottom-line-color: #2d3748;
+ --code-background-color: #2d3748;
+ --code-signature-border-color: #4a5568;
+ --menu-background-color: #2d3748;
+ --menu-font-color: #fff;
+ --menu-indent-line-color: #4a5568;
+ --menu-indent-line-active-color: #90cdf4;
+ --menu-scrollbar-color: #4a5568;
+ --menu-toggle-icon-color: #fff;
+ --menu-search-background-color: #4a5568;
+ --menu-search-font-color: #fff;
+ --toc-font-color: #90cdf4;
+ --toc-indent-line-color: #1a202c;
+}
+
+/** Reset for menus */
+.doc-nav ul, .doc-toc ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.doc-nav {
+ position: fixed;
+ width: 100%;
+ left: 0;
+ right: 0;
+ top: 0;
+ display: flex;
+ background-color: #4b6c88;
+ background-color: var(--menu-background-color);
+ color: #fff;
+ color: var(--menu-font-color);
+ flex-direction: column;
+ overflow-y: auto;
+ height: 100vh;
+ z-index: 10;
+ scrollbar-width: thin;
+ scrollbar-color: #a0aec0 transparent;
+ scrollbar-color: var(--menu-scrollbar-color) transparent;
+}
+*::-webkit-scrollbar {
+ width: 8px;
+}
+*::-webkit-scrollbar-track {
+ background: transparent;
+}
+*::-webkit-scrollbar-thumb {
+ background-color: #a0aec0;
+ background-color: var(--menu-scrollbar-color);
+ border: 3px solid transparent;
+}
+.doc-nav li {
+ line-height: 1.8;
+ font-weight: 300;
+}
+.doc-nav .content.show {
+ display: flex;
+}
+.doc-nav .content.hidden {
+ display: none;
+}
+.doc-nav #toggle-menu {
+ cursor: pointer;
+ padding: 0.3rem;
+ fill: #fff;
+ fill: var(--menu-toggle-icon-color);
+}
+.doc-nav #toggle-menu:active {
+ background-color: #00000044;
+ background-color: var(--menu-toggle-icon-hover-color);
+ border-radius: 5rem;
+}
+.doc-nav > .heading-container {
+ position: relative; /* IE11 */
+ position: sticky;
+ position: -webkit-sticky;
+ top: 0;
+ background-color: #4b6c88;
+ background-color: var(--menu-background-color);
+ z-index: 10;
+}
+.doc-nav > .heading-container > .heading {
+ display: flex;
+ padding: 0 2rem;
+ height: 56px;
+}
+.doc-nav > .heading-container > .heading > .module {
+ font-size: 1.6rem;
+ font-weight: 500;
+ margin: 0;
+}
+.doc-nav > .heading-container > .heading > .toggle-version-container {
+ display: flex;
+ align-items: center;
+}
+.doc-nav > .heading-container > .heading > .toggle-version-container > #dark-mode-toggle {
+ cursor: pointer;
+ fill: #fff;
+ display: flex;
+ visibility: hidden;
+}
+.doc-nav > .heading-container > .heading > .toggle-version-container > #dark-mode-toggle > svg {
+ width: 1.2rem;
+ height: 1.2rem;
+}
+.doc-nav > .heading-container > .heading > #search {
+ margin-top: 1rem;
+ border: none;
+ border-radius: 0.2rem;
+ padding: 0.5rem 1rem;
+ outline: none;
+ background-color: #00000044;
+ background-color: var(--menu-search-background-color);
+ color: #fff;
+ color: var(--menu-search-font-color);
+ margin-left: -0.6rem;
+ margin-right: -0.6rem;
+}
+.doc-nav > .heading-container > .heading > #search::placeholder {
+ color: #edf2f7;
+ text-transform: uppercase;
+ font-size: 12px;
+ font-weight: 600;
+}
+.doc-nav > .heading-container > .heading > #search:-ms-input-placeholder {
+ color: #edf2f7;
+ text-transform: uppercase;
+ font-size: 12px;
+ font-weight: 600;
+}
+.doc-nav > .content {
+ padding: 0 2rem 2rem 2rem;
+ display: flex;
+ flex-direction: column;
+}
+.doc-nav > .content > ul > li.active {
+ font-weight: 600;
+}
+.doc-nav > .content > ul > li.open ul {
+ display: initial;
+}
+.doc-nav > .content > ul > li.open > .menu-row > .dropdown-arrow {
+ transform: initial;
+}
+.doc-nav > .content > ul > li > .menu-row {
+ display: flex;
+ align-items: center;
+}
+.doc-nav > .content > ul > li > .menu-row > .dropdown-arrow {
+ transform: rotate(-90deg);
+ height: 18px;
+ width: 18px;
+ margin-left: calc(-18px - 0.3rem);
+ margin-right: 0.3rem;
+ cursor: pointer;
+ fill: #fff;
+ pointer-events: all;
+}
+.doc-nav > .content > ul > li > ul {
+ margin: 0.4rem 0;
+ display: none;
+}
+.doc-nav > .content > ul > li > ul > li {
+ border-color: #ffffff66;
+ border-color: var(--menu-indent-line-color);
+ border-left-width: 1.7px;
+ border-left-style: solid;
+ padding-left: 0.7rem;
+}
+.doc-nav > .content > ul > li > ul > li.active {
+ border-color: #00000066;
+ border-color: var(--menu-indent-line-active-color);
+}
+.doc-nav > .content a {
+ color: #fff;
+ color: var(--menu-font-color);
+ text-decoration: none;
+ user-select: none;
+}
+.doc-nav > .content a:hover {
+ text-decoration: underline;
+}
+
+.doc-container {
+ display: flex;
+ flex-direction: column-reverse;
+ margin-top: 56px;
+}
+
+.doc-content {
+ padding: 1rem 2rem;
+ overflow: hidden;
+}
+.doc-content a {
+ color: var(--link-color);
+}
+.doc-content > .doc-node:not(:last-child) {
+ padding: 1rem 0 3rem 0;
+}
+.doc-content > .timestamp {
+ font-size: 0.8rem;
+ color: #b8c2cc;
+ color: var(--timestamp-color);
+}
+.doc-content > .doc-node > .title {
+ display: flex;
+ align-items: center;
+ margin-bottom: 1rem;
+ border-bottom: 1px solid #f1f5f8;
+ border-bottom: 1px solid var(--title-bottom-line-color);
+}
+.doc-content > .doc-node > .title > .link {
+ margin-left: auto;
+ fill: #dae1e7;
+ fill: var(--ref-symbol-color);
+}
+.doc-content > .doc-node > .title > .link:hover {
+ fill: var(--ref-symbol-hover-color);
+}
+.doc-content > .doc-node h1 {
+ font-size: 2.5rem;
+ font-weight: 400;
+}
+.doc-content > .doc-node .signature {
+ border-color: #a0aec0;
+ border-color: var(--code-signature-border-color);
+ border-left-width: 3px;
+ border-left-style: solid;
+}
+.doc-content > .doc-node > ul > li .task-list-item-checkbox {
+ margin-right: 0.5rem;
+}
+.doc-content pre > code {
+ font-family: 'Source Code Pro', monospace;
+ font-size: 0.9rem;
+ background-color: #edf2f7;
+ background-color: var(--code-background-color);
+ padding: 1rem;
+ display: block;
+ border-radius: 0.25rem;
+ white-space: pre;
+ overflow-x: auto;
+}
+.doc-content > .doc-node > .title h1,
+.doc-content > .doc-node > .title h2,
+.doc-content > .doc-node > .title h3,
+.doc-content > .doc-node > .title h4,
+.doc-content > .doc-node > .title h5,
+.doc-content > .doc-node > .title h6 {
+ font-weight: 400;
+ padding-bottom: 0.8rem;
+ margin: 0;
+}
+.doc-content > .doc-node > .title h1 a,
+.doc-content > .doc-node > .title h2 a,
+.doc-content > .doc-node > .title h3 a,
+.doc-content > .doc-node > .title h4 a,
+.doc-content > .doc-node > .title h5 a,
+.doc-content > .doc-node > .title h6 a {
+ text-decoration: none;
+ color: #dae1e7;
+ color: var(--ref-symbol-color);
+}
+.doc-content > .doc-node > .title h1 a:hover,
+.doc-content > .doc-node > .title h2 a:hover,
+.doc-content > .doc-node > .title h3 a:hover,
+.doc-content > .doc-node > .title h4 a:hover,
+.doc-content > .doc-node > .title h5 a:hover,
+.doc-content > .doc-node > .title h6 a:hover {
+ color: var(--ref-symbol-hover-color);
+}
+
+.doc-toc {
+ right: 0;
+ top: 0;
+ height: 100%;
+ overflow-y: auto;
+ padding: 2rem;
+ width: 100%;
+ box-sizing: border-box;
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+}
+.doc-toc::-webkit-scrollbar {
+ display: none;
+}
+.doc-toc li {
+ line-height: 1.5;
+}
+.doc-toc a {
+ color: #2779bd;
+ color: var(--toc-font-color);
+ font-size: 0.9rem;
+ font-weight: 600;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: block;
+ text-decoration: none;
+}
+.doc-toc a:hover {
+ text-decoration: underline;
+}
+.doc-toc li ul {
+ border-color :#dae1e7;
+ border-color: var(--toc-indent-line-color);
+ border-left-width: 2px;
+ border-left-style: solid;
+ padding-left: 0.8rem;
+ margin: 0.2rem 0 0.2rem;
+ font-size: 0.7rem;
+ list-style: none;
+}
+.doc-toc li ul a {
+ font-weight: 400;
+}
+
+/* Medium screen and up */
+@media (min-width: 768px) {
+ .doc-container {
+ flex-direction: row;
+ }
+
+ .doc-content {
+ flex: 1;
+ }
+
+ .doc-toc {
+ padding: 1rem 1rem 0 1rem;
+ position: relative; /* IE11 */
+ position: sticky;
+ position: -webkit-sticky;
+ align-self: flex-start;
+ top: 56px;
+ height: auto;
+ height: 100vh;
+ min-width: 200px;
+ width: auto;
+ max-width: 300px;
+ }
+ .doc-toc > ul {
+ padding-bottom: 1rem;
+ }
+}
+
+@media (max-width: 1023px) {
+ .doc-nav.hidden {
+ height: auto;
+ }
+ .doc-nav > .heading-container > .heading {
+ align-items: center;
+ }
+ .doc-nav > .heading-container > .heading > .toggle-version-container {
+ flex-grow: 1;
+ padding: 0 1rem;
+ justify-content: space-between;
+ }
+ .doc-nav > .heading-container > .heading > #search {
+ display: none;
+ }
+}
+
+@media (min-width: 1024px) {
+ .doc-nav {
+ width: 300px;
+ }
+ .doc-nav #toggle-menu {
+ display: none;
+ }
+ .doc-nav > .heading-container > .heading {
+ height: auto;
+ padding-top: 1rem;
+ padding-bottom: 1rem;
+ flex-direction: column-reverse;
+ justify-content: center;
+ }
+ .doc-nav > .heading-container > .heading > .toggle-version-container {
+ align-items: center;
+ margin-bottom: 0.2rem;
+ display: flex;
+ flex-direction: row-reverse;
+ }
+ .doc-nav > .heading-container > .heading > .toggle-version-container > #dark-mode-toggle {
+ margin-right: auto;
+ }
+ .doc-nav .content.show,
+ .doc-nav .content.hidden {
+ display: flex;
+ }
+
+ .doc-container {
+ margin-top: 0;
+ margin-left: 300px;
+ }
+
+ .doc-toc {
+ top: 0;
+ }
+}
diff --git a/cmd/tools/vdoc-resources/doc.js b/cmd/tools/vdoc-resources/doc.js
new file mode 100644
index 0000000000..a643d6d564
--- /dev/null
+++ b/cmd/tools/vdoc-resources/doc.js
@@ -0,0 +1,66 @@
+(function() {
+ // Mobile view menu toggle button
+ var toggle = document.getElementById("toggle-menu");
+ toggle.addEventListener("click", function(ev) {
+ document.querySelectorAll(".doc-nav").forEach(function(el) {
+ el.classList.toggle("hidden");
+ });
+ document.querySelectorAll(".doc-nav .content").forEach(function(el) {
+ el.classList.toggle("hidden");
+ el.classList.toggle("show");
+ });
+ });
+
+ // Dark mode
+ var html = document.getElementsByTagName('html')[0];
+ var darkModeToggle = document.getElementById('dark-mode-toggle');
+ darkModeToggle.addEventListener('click', function() {
+ html.classList.toggle('dark');
+ var isDarkModeEnabled = html.classList.contains('dark');
+ localStorage.setItem('dark-mode', isDarkModeEnabled);
+ });
+ if (localStorage.getItem('dark-mode') === 'true') {
+ html.classList.add('dark');
+ }
+
+ // Check if css var() is supported and enable dark mode toggle
+ if (window.CSS && CSS.supports('color', 'var(--fake-var)')) {
+ darkModeToggle.style.visibility = 'unset';
+ }
+
+ // Search
+ var searchInput = document.getElementById('search');
+ searchInput.addEventListener('input', function(e) {
+ var searchValue = e.target.value.toLowerCase();
+ var menuItems = document.querySelectorAll('.content > ul > li');
+ for (var i = 0; i < menuItems.length; i++) {
+ var menuItem = menuItems[i];
+ var links = menuItem.querySelectorAll('a');
+ var hasResult = false;
+ for (var li = 0; li < links.length; li++) {
+ var link = links[li];
+ if (!searchValue || link.text.toLowerCase().indexOf(searchValue) !== -1) {
+ hasResult = true;
+ }
+ if (li > 0) {
+ if (!searchValue || link.text.toLowerCase().indexOf(searchValue) !== -1) {
+ link.style.display = '';
+ } else {
+ link.style.display = 'none';
+ }
+ }
+ }
+ menuItem.style.display = !searchValue || hasResult ? '' : 'none';
+ }
+ });
+
+ // Collapse
+ var dropdownArrows = document.querySelectorAll('.dropdown-arrow');
+ for (var i = 0; i < dropdownArrows.length; i++) {
+ var dropdownArrow = dropdownArrows[i];
+ dropdownArrow.addEventListener('click', function(e) {
+ var parent = e.target.parentElement.parentElement.parentElement;
+ parent.classList.toggle('open');
+ });
+ }
+})();
diff --git a/cmd/tools/vdoc-resources/light.svg b/cmd/tools/vdoc-resources/light.svg
new file mode 100644
index 0000000000..21606c9cd3
--- /dev/null
+++ b/cmd/tools/vdoc-resources/light.svg
@@ -0,0 +1 @@
+
diff --git a/cmd/tools/vdoc-resources/link.svg b/cmd/tools/vdoc-resources/link.svg
new file mode 100644
index 0000000000..60d93bb2e9
--- /dev/null
+++ b/cmd/tools/vdoc-resources/link.svg
@@ -0,0 +1 @@
+
diff --git a/cmd/tools/vdoc-resources/menu.svg b/cmd/tools/vdoc-resources/menu.svg
new file mode 100644
index 0000000000..c069b00d90
--- /dev/null
+++ b/cmd/tools/vdoc-resources/menu.svg
@@ -0,0 +1 @@
+
diff --git a/cmd/tools/vdoc.v b/cmd/tools/vdoc.v
index 0dd70b9ee2..db2ba25b59 100644
--- a/cmd/tools/vdoc.v
+++ b/cmd/tools/vdoc.v
@@ -10,6 +10,12 @@ import v.doc
import v.util
import v.vmod
+const (
+ exe_path = os.executable()
+ exe_dir = os.dir(exe_path)
+ res_path = os.join_path(exe_dir, 'vdoc-resources')
+)
+
enum OutputType {
html
markdown
@@ -19,15 +25,15 @@ enum OutputType {
}
struct DocConfig {
- pub_only bool = true
- show_loc bool = false // for plaintext
- serve_http bool = false // for html
- is_multi bool = false
+ pub_only bool = true
+ show_loc bool = false // for plaintext
+ serve_http bool = false // for html
+ is_multi bool = false
include_readme bool = false
mut:
- opath string
+ opath string
src_path string
- docs []doc.Doc
+ docs []doc.Doc
manifest vmod.Manifest
}
@@ -90,6 +96,9 @@ fn get_src_link(repo_url string, file_name string, line_nr int) string {
'git.sir.ht' { '/tree/master/$file_name' }
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 '' }
url.fragment = 'L$line_nr'
return url.str()
@@ -123,20 +132,22 @@ fn (cfg DocConfig) gen_html(idx int) string {
mut toc := strings.new_builder(200)
mut doc_node_html := fn (dd doc.DocNode, link string, head bool) string {
mut dnw := strings.new_builder(200)
+ link_svg := ''
head_tag := if head { 'h1' } else { 'h2' }
md_content := markdown.to_html(dd.comment)
dnw.writeln(' [Source]${dd.content}
')
+ dnw.writeln('
')
dnw.writeln(md_content)
- if link.len != 0 {
- dnw.writeln('${dd.content}
Contents
\n