diff --git a/cmd/tools/vdoc/resources/doc.css b/cmd/tools/vdoc/resources/doc.css index 9e8bf94e97..54b968c689 100644 --- a/cmd/tools/vdoc/resources/doc.css +++ b/cmd/tools/vdoc/resources/doc.css @@ -17,6 +17,11 @@ --menu-toggle-icon-hover-color: #00000044; --menu-search-background-color: #00000044; --menu-search-font-color: #fff; + --menu-search-result-background-hover-color: #00000021; + --menu-search-separator-color: #00000044; + --menu-search-title-text-color: #d5efff; + --menu-search-badge-background-color: #00000044; + --menu-search-badge-background-hover-color: #0000004d; --toc-text-color: #2779bd; --toc-indicator-color: #4299e1; --code-default-text-color: #5c6e74; @@ -49,11 +54,15 @@ --menu-background-color: #2d3748; --menu-text-color: #fff; --menu-indent-line-color: #4a5568; - --menu-indent-line-active-color: #90cdf4; + --menu-indent-line-active-color: #90cdf4; /*#4a5568*/ --menu-scrollbar-color: #4a5568; --menu-toggle-icon-color: #fff; --menu-search-background-color: #4a5568; --menu-search-font-color: #fff; + --menu-search-separator-color: #4a5568; + --menu-search-title-text-color: #90cdf4; + --menu-search-badge-background-color: #4a5568; + --menu-search-badge-background-hover-color: #4a5568; --toc-text-color: #90cdf4; --toc-indicator-color: #4299e1; --code-default-text-color: #cbd5e0; @@ -111,7 +120,7 @@ body { scrollbar-width: thin; scrollbar-color: #a0aec0 transparent; scrollbar-color: var(--menu-scrollbar-color) transparent; - font-family: 'Work Sans', sans-serif; + font-family: "Work Sans", sans-serif; } *::-webkit-scrollbar { width: 4px; @@ -125,7 +134,7 @@ body { background-color: var(--menu-scrollbar-color); border: 3px solid transparent; } -.doc-nav li { +.doc-nav .content li { line-height: 1.8; } .doc-nav .content.show { @@ -245,7 +254,7 @@ body { } .doc-nav > .content > ul > li > ul > li.active { border-color: #00000066; - border-color: var(--menu-indent-line-active-color); + border-color: var(--menu-search-result-hover-background-color); } .doc-nav > .content a { color: #fff; @@ -256,6 +265,69 @@ body { .doc-nav > .content a:hover { text-decoration: underline; } +.doc-nav .search { + display: none; +} +.doc-nav .search li { + line-height: 1.5; +} +.doc-nav > .search .result:hover { + background-color: #00000021; + background-color: var(--menu-search-result-background-hover-color); +} +.doc-nav > .search .result:hover > .link > .definition > .badge { + background-color: #0000004d; + background-color: var(--menu-search-badge-background-hover-color); +} +.doc-nav > .search .result > .link { + padding: 0.5rem 1.4rem; + text-decoration: none; + color: #fff; + color: var(--menu-text-color); + display: block; +} +.doc-nav > .search .result > .link > .definition { + display: flex; +} +.doc-nav > .search .result > .link > .definition > .title { + color: #90cdf4; + color: var(--menu-search-title-text-color); + font-size: 0.875rem; + font-weight: 500; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.doc-nav > .search .result > .link > .definition > .badge { + font-size: 0.75rem; + display: inline-flex; + padding: 0 0.5rem; + background-color: #00000044; + background-color: var(--menu-search-badge-background-color); + margin-left: auto; + align-items: center; + border-radius: 9999px; + font-weight: 500; +} +.doc-nav > .search .result > .link > .description { + font-family: Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 0.75rem; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin-top: 0.25rem; +} +.doc-nav > .search > hr.separator { + margin: 0.5rem 0; + border-color: #00000044; + border-color: var(--menu-search-separator-color); + box-sizing: content-box; + height: 0; + border-width: 0; + border-top-width: 1px; + border-style: solid; + overflow: visible; +} /* Main content */ .doc-scrollview { @@ -305,7 +377,7 @@ body { } .doc-content > .doc-node > .title { display: flex; - font-family: 'Work Sans', sans-serif; + font-family: "Work Sans", sans-serif; font-weight: 500; padding: 0.3rem; align-items: center; @@ -391,7 +463,7 @@ body { box-sizing: border-box; -ms-overflow-style: none; scrollbar-width: none; - font-family: 'Work Sans', sans-serif; + font-family: "Work Sans", sans-serif; } .doc-toc::-webkit-scrollbar { display: none; diff --git a/cmd/tools/vdoc/resources/doc.js b/cmd/tools/vdoc/resources/doc.js index 7fb63d19a6..ac19dd2978 100644 --- a/cmd/tools/vdoc/resources/doc.js +++ b/cmd/tools/vdoc/resources/doc.js @@ -80,29 +80,114 @@ function setupDarkMode() { function setupSearch() { var searchInput = document.getElementById('search'); - searchInput.addEventListener('input', function(e) { + var onInputChange = debounce(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'; - } + var menu = document.querySelector('.doc-nav > .content'); + var search = document.querySelector('.doc-nav > .search'); + if (searchValue === '') { + // reset to default + menu.style.display = ''; + search.style.display = ''; + } else if (searchValue.length > 2) { + // search for less than 3 characters can display too much results + search.innerHTML = ''; + menu.style.display = 'none'; + search.style.display = 'block'; + // cache length for performance + var foundModule = false; + var searchModuleIndexLength = searchModuleIndex.length; + var ul = document.createElement('ul'); + search.appendChild(ul); + for (var i = 0; i < searchModuleIndexLength; i++) { + // no toLowerCase needed because modules are always lowercase + var title = searchModuleIndex[i]; + if (title.indexOf(searchValue) === -1) { + continue } + foundModule = true; + // [description, link] + var data = searchModuleData[i]; + var description = data[0]; + var link = data[1]; + var el = createSearchResult({ + link: link, + title: title, + description: description, + badge: 'module', + }); + ul.appendChild(el); + } + if (foundModule) { + var hr = document.createElement('hr'); + hr.classList.add('separator'); + search.appendChild(hr); + } + var searchIndexLength = searchIndex.length; + var results = []; + for (var i = 0; i < searchIndexLength; i++) { + var title = searchIndex[i].toLowerCase(); + if (title.indexOf(searchValue) === -1) { + continue + } + // [badge, description, link] + var data = searchData[i]; + var badge = data[0]; + var description = data[1]; + var link = data[2]; + var prefix = data[3]; + results.push({ + badge: badge, + description: description, + link: link, + title: prefix + ' ' + title, + }); + } + results.sort(function(a, b) { + if (a.title < b.title) { + return -1; + } + if (a.title > b.title) { + return 1; + } + return 0; + }); + var ul = document.createElement('ul'); + search.appendChild(ul); + for (var i = 0; i < results.length; i++) { + var result = results[i]; + var el = createSearchResult(result); + ul.appendChild(el); } - menuItem.style.display = !searchValue || hasResult ? '' : 'none'; } }); + searchInput.addEventListener('input', onInputChange); +} + +function createSearchResult(data) { + var li = document.createElement('li'); + li.classList.add('result'); + var a = document.createElement('a'); + a.href = data.link; + a.classList.add('link'); + li.appendChild(a); + var defintion = document.createElement('div'); + defintion.classList.add('definition'); + a.appendChild(defintion); + if (data.description) { + var description = document.createElement('div'); + description.classList.add('description'); + description.textContent = data.description; + a.appendChild(description); + } + var title = document.createElement('span'); + title.classList.add('title'); + title.textContent = data.title; + defintion.appendChild(title); + var badge = document.createElement('badge'); + badge.classList.add('badge'); + badge.textContent = data.badge; + defintion.appendChild(badge); + return li; } function setupCollapse() { @@ -115,3 +200,14 @@ function setupCollapse() { }); } } + +function debounce(func, timeout) { + var timer; + return (...args) => { + const next = () => func(...args); + if (timer) { + clearTimeout(timer); + } + timer = setTimeout(next, timeout > 0 ? timeout : 300); + } +} diff --git a/cmd/tools/vdoc/vdoc.v b/cmd/tools/vdoc/vdoc.v index db177d4bff..32983f848b 100644 --- a/cmd/tools/vdoc/vdoc.v +++ b/cmd/tools/vdoc/vdoc.v @@ -66,7 +66,7 @@ const (