vdoc: native syntax highlighting, system font, and intergrate normalize.css

pull/5231/head
Ned Palacios 2020-06-06 13:56:17 +08:00 committed by GitHub
parent c2fe4ffa85
commit c1ccd56119
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 658 additions and 369 deletions

View File

@ -1,430 +1,625 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
html {
line-height: 1.15;
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
}
main {
display: block;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
pre {
font-family: monospace, monospace;
font-size: 1em;
}
a {
background-color: transparent;
}
abbr[title] {
border-bottom: none;
text-decoration: underline;
text-decoration: underline dotted;
}
b,
strong {
font-weight: bolder;
}
code,
kbd,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
img {
border-style: none;
}
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
font-size: 100%;
line-height: 1.15;
margin: 0;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
fieldset {
padding: 0.35em 0.75em 0.625em;
}
legend {
box-sizing: border-box;
color: inherit;
display: table;
max-width: 100%;
padding: 0;
white-space: normal;
}
progress {
vertical-align: baseline;
}
textarea {
overflow: auto;
}
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
padding: 0;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
summary {
display: list-item;
}
template {
display: none;
}
[hidden] {
display: none;
}
:root { :root {
--background-color: #fff; --background-color: #fff;
--timestamp-color: #b8c2cc; --timestamp-color: #b8c2cc;
--link-color: #2779bd; --link-color: #2779bd;
--font-color: #000; --font-color: #000;
--ref-symbol-color: #dae1e7; --ref-symbol-color: #dae1e7;
--ref-symbol-hover-color: #b8c2cc; --ref-symbol-hover-color: #b8c2cc;
--title-bottom-line-color: #f1f5f8; --title-bottom-line-color: #f1f5f8;
--code-signature-border-color: #a0aec0; --code-signature-border-color: #a0aec0;
--menu-background-color: #4b6c88; --menu-background-color: #4b6c88;
--menu-font-color: #fff; --menu-font-color: #fff;
--menu-indent-line-color: #ffffff66; --menu-indent-line-color: #ffffff66;
--menu-indent-line-active-color: #00000066; --menu-indent-line-active-color: #00000066;
--menu-scrollbar-color: #a0aec0; --menu-scrollbar-color: #a0aec0;
--menu-toggle-icon-color: #fff; --menu-toggle-icon-color: #fff;
--menu-toggle-icon-hover-color: #00000044; --menu-toggle-icon-hover-color: #00000044;
--menu-search-background-color: #00000044; --menu-search-background-color: #00000044;
--menu-search-font-color: #fff; --menu-search-font-color: #fff;
--toc-font-color: #2779bd; --toc-font-color: #2779bd;
--toc-indent-line-color: #dae1e7; --toc-indent-line-color: #dae1e7;
} }
:root.dark .dark-icon { :root.dark .dark-icon {
display: none; display: none;
} }
:root:not(.dark) .light-icon { :root:not(.dark) .light-icon {
display: none; display: none;
} }
body { body {
font-family: 'Inter', sans-serif; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
background-color: #fff; background-color: #fff;
background-color: var(--background-color); background-color: var(--background-color);
color: #000; color: #000;
color: var(--font-color); color: var(--font-color);
} }
.dark body { .dark body {
--background-color: #1a202c; --background-color: #1a202c;
--timestamp-color: #b8c2cc; --timestamp-color: #b8c2cc;
--font-color: #fff; --font-color: #fff;
--link-color: #90cdf4; --link-color: #90cdf4;
--ref-symbol-color: #2d3748; --ref-symbol-color: #2d3748;
--ref-symbol-hover-color: #4a5568; --ref-symbol-hover-color: #4a5568;
--title-bottom-line-color: #2d3748; --title-bottom-line-color: #2d3748;
--code-signature-border-color: #4a5568; --code-signature-border-color: #4a5568;
--menu-background-color: #2d3748; --menu-background-color: #2d3748;
--menu-font-color: #fff; --menu-font-color: #fff;
--menu-indent-line-color: #4a5568; --menu-indent-line-color: #4a5568;
--menu-indent-line-active-color: #90cdf4; --menu-indent-line-active-color: #90cdf4;
--menu-scrollbar-color: #4a5568; --menu-scrollbar-color: #4a5568;
--menu-toggle-icon-color: #fff; --menu-toggle-icon-color: #fff;
--menu-search-background-color: #4a5568; --menu-search-background-color: #4a5568;
--menu-search-font-color: #fff; --menu-search-font-color: #fff;
--toc-font-color: #90cdf4; --toc-font-color: #90cdf4;
--toc-indent-line-color: #1a202c; --toc-indent-line-color: #1a202c;
} }
/** Reset for menus */ /** Reset for menus */
.doc-nav ul, .doc-toc ul {
list-style: none; .doc-nav ul,
padding: 0; .doc-toc ul {
margin: 0; list-style: none;
padding: 0;
margin: 0;
} }
.doc-nav { .doc-nav {
position: fixed; position: fixed;
width: 100%; width: 100%;
left: 0; left: 0;
right: 0; right: 0;
top: 0; top: 0;
display: flex; display: flex;
background-color: #4b6c88; background-color: #4b6c88;
background-color: var(--menu-background-color); background-color: var(--menu-background-color);
color: #fff; color: #fff;
color: var(--menu-font-color); color: var(--menu-font-color);
flex-direction: column; flex-direction: column;
overflow-y: auto; overflow-y: auto;
height: 100vh; height: 100vh;
z-index: 10; z-index: 10;
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: #a0aec0 transparent; scrollbar-color: #a0aec0 transparent;
scrollbar-color: var(--menu-scrollbar-color) transparent; scrollbar-color: var(--menu-scrollbar-color) transparent;
} }
*::-webkit-scrollbar { *::-webkit-scrollbar {
width: 8px; width: 8px;
} }
*::-webkit-scrollbar-track { *::-webkit-scrollbar-track {
background: transparent; background: transparent;
} }
*::-webkit-scrollbar-thumb { *::-webkit-scrollbar-thumb {
background-color: #a0aec0; background-color: #a0aec0;
background-color: var(--menu-scrollbar-color); background-color: var(--menu-scrollbar-color);
border: 3px solid transparent; border: 3px solid transparent;
} }
.doc-nav li { .doc-nav li {
line-height: 1.8; line-height: 1.8;
font-weight: 300; font-weight: 300;
} }
.doc-nav .content.show { .doc-nav .content.show {
display: flex; display: flex;
} }
.doc-nav .content.hidden { .doc-nav .content.hidden {
display: none; display: none;
} }
.doc-nav #toggle-menu { .doc-nav #toggle-menu {
cursor: pointer; cursor: pointer;
padding: 0.3rem; padding: 0.3rem;
fill: #fff; fill: #fff;
fill: var(--menu-toggle-icon-color); fill: var(--menu-toggle-icon-color);
} }
.doc-nav #toggle-menu:active { .doc-nav #toggle-menu:active {
background-color: #00000044; background-color: #00000044;
background-color: var(--menu-toggle-icon-hover-color); background-color: var(--menu-toggle-icon-hover-color);
border-radius: 5rem; border-radius: 5rem;
} }
.doc-nav > .heading-container {
position: relative; /* IE11 */ .doc-nav>.heading-container {
position: sticky; position: relative;
position: -webkit-sticky; /* IE11 */
top: 0; position: sticky;
background-color: #4b6c88; position: -webkit-sticky;
background-color: var(--menu-background-color); top: 0;
z-index: 10; background-color: #4b6c88;
background-color: var(--menu-background-color);
z-index: 10;
} }
.doc-nav > .heading-container > .heading {
display: flex; .doc-nav>.heading-container>.heading {
padding: 0 2rem; display: flex;
height: 56px; padding: 0 2rem;
height: 56px;
} }
.doc-nav > .heading-container > .heading > .module {
font-size: 1.6rem; .doc-nav>.heading-container>.heading>.module {
font-weight: 500; font-size: 1.6rem;
margin: 0; font-weight: 500;
margin: 0;
} }
.doc-nav > .heading-container > .heading > .toggle-version-container {
display: flex; .doc-nav>.heading-container>.heading>.toggle-version-container {
align-items: center; display: flex;
align-items: center;
} }
.doc-nav > .heading-container > .heading > .toggle-version-container > #dark-mode-toggle {
cursor: pointer; .doc-nav>.heading-container>.heading>.toggle-version-container>#dark-mode-toggle {
fill: #fff; cursor: pointer;
display: flex; fill: #fff;
visibility: hidden; display: flex;
visibility: hidden;
} }
.doc-nav > .heading-container > .heading > .toggle-version-container > #dark-mode-toggle > svg {
width: 1.2rem; .doc-nav>.heading-container>.heading>.toggle-version-container>#dark-mode-toggle>svg {
height: 1.2rem; width: 1.2rem;
height: 1.2rem;
} }
.doc-nav > .heading-container > .heading > #search {
margin-top: 1rem; .doc-nav>.heading-container>.heading>#search {
border: none; margin-top: 1rem;
border-radius: 0.2rem; border: none;
padding: 0.5rem 1rem; border-radius: 0.2rem;
outline: none; padding: 0.5rem 1rem;
background-color: #00000044; outline: none;
background-color: var(--menu-search-background-color); background-color: #00000044;
color: #fff; background-color: var(--menu-search-background-color);
color: var(--menu-search-font-color); color: #fff;
margin-left: -0.6rem; color: var(--menu-search-font-color);
margin-right: -0.6rem; margin-left: -0.6rem;
margin-right: -0.6rem;
} }
.doc-nav > .heading-container > .heading > #search::placeholder {
color: #edf2f7; .doc-nav>.heading-container>.heading>#search::placeholder {
text-transform: uppercase; color: #edf2f7;
font-size: 12px; text-transform: uppercase;
font-weight: 600; font-size: 12px;
font-weight: 600;
} }
.doc-nav > .heading-container > .heading > #search:-ms-input-placeholder {
color: #edf2f7; .doc-nav>.heading-container>.heading>#search:-ms-input-placeholder {
text-transform: uppercase; color: #edf2f7;
font-size: 12px; text-transform: uppercase;
font-weight: 600; font-size: 12px;
font-weight: 600;
} }
.doc-nav > .content {
padding: 0 2rem 2rem 2rem; .doc-nav>.content {
display: flex; padding: 0 2rem 2rem 2rem;
flex-direction: column; display: flex;
flex-direction: column;
} }
.doc-nav > .content > ul > li.active {
font-weight: 600; .doc-nav>.content>ul>li.active {
font-weight: 600;
} }
.doc-nav > .content > ul > li.open ul {
display: initial; .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.open>.menu-row>.dropdown-arrow {
transform: initial;
} }
.doc-nav > .content > ul > li > .menu-row {
display: flex; .doc-nav>.content>ul>li>.menu-row {
align-items: center; display: flex;
align-items: center;
} }
.doc-nav > .content > ul > li > .menu-row > .dropdown-arrow {
transform: rotate(-90deg); .doc-nav>.content>ul>li>.menu-row>.dropdown-arrow {
height: 18px; transform: rotate(-90deg);
width: 18px; height: 18px;
margin-left: calc(-18px - 0.3rem); width: 18px;
margin-right: 0.3rem; margin-left: calc(-18px - 0.3rem);
cursor: pointer; margin-right: 0.3rem;
fill: #fff; cursor: pointer;
pointer-events: all; fill: #fff;
pointer-events: all;
} }
.doc-nav > .content > ul > li > ul {
margin: 0.4rem 0; .doc-nav>.content>ul>li>ul {
display: none; margin: 0.4rem 0;
display: none;
} }
.doc-nav > .content > ul > li > ul > li {
border-color: #ffffff66; .doc-nav>.content>ul>li>ul>li {
border-color: var(--menu-indent-line-color); border-color: #ffffff66;
border-left-width: 1.7px; border-color: var(--menu-indent-line-color);
border-left-style: solid; border-left-width: 1.7px;
padding-left: 0.7rem; border-left-style: solid;
padding-left: 0.7rem;
} }
.doc-nav > .content > ul > li > ul > li.active {
border-color: #00000066; .doc-nav>.content>ul>li>ul>li.active {
border-color: var(--menu-indent-line-active-color); border-color: #00000066;
border-color: var(--menu-indent-line-active-color);
} }
.doc-nav > .content a {
color: #fff; .doc-nav>.content a {
color: var(--menu-font-color); color: #fff;
text-decoration: none; color: var(--menu-font-color);
user-select: none; text-decoration: none;
user-select: none;
} }
.doc-nav > .content a:hover {
text-decoration: underline; .doc-nav>.content a:hover {
text-decoration: underline;
} }
.doc-container { .doc-container {
display: flex; display: flex;
flex-direction: column-reverse; flex-direction: column-reverse;
margin-top: 56px; margin-top: 56px;
} }
.doc-content { .doc-content {
padding: 1rem 2rem; padding: 1rem 2rem;
overflow: hidden; overflow: hidden;
} }
.doc-content a { .doc-content a {
color: var(--link-color); color: var(--link-color);
} }
.doc-content > .doc-node:not(:last-child) {
padding: 1rem 0 3rem 0; .doc-content>.doc-node:not(:last-child) {
padding: 1rem 0 3rem 0;
} }
.doc-content > .timestamp {
font-size: 0.8rem; .doc-content>.timestamp {
color: #b8c2cc; font-size: 0.8rem;
color: var(--timestamp-color); color: #b8c2cc;
color: var(--timestamp-color);
} }
.doc-content > .doc-node > .title {
display: flex; .doc-content>.doc-node>.title {
align-items: center; display: flex;
margin-bottom: 1rem; align-items: center;
border-bottom: 1px solid #f1f5f8; margin-bottom: 1rem;
border-bottom: 1px solid var(--title-bottom-line-color); border-bottom: 1px solid #f1f5f8;
border-bottom: 1px solid var(--title-bottom-line-color);
} }
.doc-content > .doc-node > .title > .link {
margin-left: auto; .doc-content>.doc-node>.title>.link {
fill: #dae1e7; margin-left: auto;
fill: var(--ref-symbol-color); fill: #dae1e7;
fill: var(--ref-symbol-color);
} }
.doc-content > .doc-node > .title > .link:hover {
fill: var(--ref-symbol-hover-color); .doc-content>.doc-node>.title>.link:hover {
fill: var(--ref-symbol-hover-color);
} }
.doc-content > .doc-node h1 {
font-size: 2.5rem; .doc-content>.doc-node h1 {
font-weight: 400; font-size: 2.5rem;
font-weight: 400;
} }
.doc-content > .doc-node .signature {
border-color: #a0aec0; .doc-content>.doc-node .signature {
border-color: var(--code-signature-border-color); border-color: #a0aec0;
border-left-width: 3px; border-color: var(--code-signature-border-color);
border-left-style: solid; border-left-width: 3px;
border-left-style: solid;
} }
.doc-content > .doc-node > ul > li .task-list-item-checkbox {
margin-right: 0.5rem; .doc-content>.doc-node>ul>li .task-list-item-checkbox {
margin-right: 0.5rem;
} }
.doc-content > .doc-node > .title h1,
.doc-content > .doc-node > .title h2, .doc-content>.doc-node>.title h1,
.doc-content > .doc-node > .title h3, .doc-content>.doc-node>.title h2,
.doc-content > .doc-node > .title h4, .doc-content>.doc-node>.title h3,
.doc-content > .doc-node > .title h5, .doc-content>.doc-node>.title h4,
.doc-content > .doc-node > .title h6 { .doc-content>.doc-node>.title h5,
font-weight: 400; .doc-content>.doc-node>.title h6 {
padding-bottom: 0.8rem; font-weight: 400;
margin: 0; 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 h1 a,
.doc-content > .doc-node > .title h3 a, .doc-content>.doc-node>.title h2 a,
.doc-content > .doc-node > .title h4 a, .doc-content>.doc-node>.title h3 a,
.doc-content > .doc-node > .title h5 a, .doc-content>.doc-node>.title h4 a,
.doc-content > .doc-node > .title h6 a { .doc-content>.doc-node>.title h5 a,
text-decoration: none; .doc-content>.doc-node>.title h6 a {
color: #dae1e7; text-decoration: none;
color: var(--ref-symbol-color); 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 h1 a:hover,
.doc-content > .doc-node > .title h3 a:hover, .doc-content>.doc-node>.title h2 a:hover,
.doc-content > .doc-node > .title h4 a:hover, .doc-content>.doc-node>.title h3 a:hover,
.doc-content > .doc-node > .title h5 a:hover, .doc-content>.doc-node>.title h4 a:hover,
.doc-content > .doc-node > .title h6 a:hover { .doc-content>.doc-node>.title h5 a:hover,
color: var(--ref-symbol-hover-color); .doc-content>.doc-node>.title h6 a:hover {
color: var(--ref-symbol-hover-color);
} }
.doc-toc { .doc-toc {
right: 0; right: 0;
top: 0; top: 0;
height: 100%; height: 100%;
overflow-y: auto; overflow-y: auto;
padding: 2rem; padding: 2rem;
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
-ms-overflow-style: none; -ms-overflow-style: none;
scrollbar-width: none; scrollbar-width: none;
} }
.doc-toc::-webkit-scrollbar { .doc-toc::-webkit-scrollbar {
display: none; display: none;
} }
.doc-toc li { .doc-toc li {
line-height: 1.5; line-height: 1.5;
} }
.doc-toc a { .doc-toc a {
color: #2779bd; color: #2779bd;
color: var(--toc-font-color); color: var(--toc-font-color);
font-size: 0.9rem; font-size: 0.9rem;
font-weight: 600; font-weight: 600;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
display: block; display: block;
text-decoration: none; text-decoration: none;
} }
.doc-toc a:hover { .doc-toc a:hover {
text-decoration: underline; text-decoration: underline;
} }
.doc-toc li ul { .doc-toc li ul {
border-color :#dae1e7; border-color: #dae1e7;
border-color: var(--toc-indent-line-color); border-color: var(--toc-indent-line-color);
border-left-width: 2px; border-left-width: 2px;
border-left-style: solid; border-left-style: solid;
padding-left: 0.8rem; padding-left: 0.8rem;
margin: 0.2rem 0 0.2rem; margin: 0.2rem 0 0.2rem;
font-size: 0.7rem; font-size: 0.7rem;
list-style: none; list-style: none;
} }
.doc-toc li ul a { .doc-toc li ul a {
font-weight: 400; font-weight: 400;
} }
/* Medium screen and up */ /* Medium screen and up */
@media (min-width: 768px) { @media (min-width: 768px) {
.doc-container { .doc-container {
flex-direction: row; flex-direction: row;
} }
.doc-content {
.doc-content { flex: 1;
flex: 1; }
} .doc-toc {
padding: 1rem 1rem 0 1rem;
.doc-toc { position: relative;
padding: 1rem 1rem 0 1rem; /* IE11 */
position: relative; /* IE11 */ position: sticky;
position: sticky; position: -webkit-sticky;
position: -webkit-sticky; align-self: flex-start;
align-self: flex-start; top: 56px;
top: 56px; height: auto;
height: auto; height: 100vh;
height: 100vh; min-width: 200px;
min-width: 200px; width: auto;
width: auto; max-width: 300px;
max-width: 300px; }
} .doc-toc>ul {
.doc-toc > ul { padding-bottom: 1rem;
padding-bottom: 1rem; }
}
} }
@media (max-width: 1023px) { @media (max-width: 1023px) {
.doc-nav.hidden { .doc-nav.hidden {
height: auto; height: auto;
} }
.doc-nav > .heading-container > .heading { .doc-nav>.heading-container>.heading {
align-items: center; align-items: center;
} }
.doc-nav > .heading-container > .heading > .toggle-version-container { .doc-nav>.heading-container>.heading>.toggle-version-container {
flex-grow: 1; flex-grow: 1;
padding: 0 1rem; padding: 0 1rem;
justify-content: space-between; justify-content: space-between;
} }
.doc-nav > .heading-container > .heading > #search { .doc-nav>.heading-container>.heading>#search {
display: none; display: none;
} }
} }
@media (min-width: 1024px) { @media (min-width: 1024px) {
.doc-nav { .doc-nav {
width: 300px; width: 300px;
} }
.doc-nav #toggle-menu { .doc-nav #toggle-menu {
display: none; display: none;
} }
.doc-nav > .heading-container > .heading { .doc-nav>.heading-container>.heading {
height: auto; height: auto;
padding-top: 1rem; padding-top: 1rem;
padding-bottom: 1rem; padding-bottom: 1rem;
flex-direction: column-reverse; flex-direction: column-reverse;
justify-content: center; justify-content: center;
} }
.doc-nav > .heading-container > .heading > .toggle-version-container { .doc-nav>.heading-container>.heading>.toggle-version-container {
align-items: center; align-items: center;
margin-bottom: 0.2rem; margin-bottom: 0.2rem;
display: flex; display: flex;
flex-direction: row-reverse; flex-direction: row-reverse;
} }
.doc-nav > .heading-container > .heading > .toggle-version-container > #dark-mode-toggle { .doc-nav>.heading-container>.heading>.toggle-version-container>#dark-mode-toggle {
margin-right: auto; margin-right: auto;
} }
.doc-nav .content.show, .doc-nav .content.show,
.doc-nav .content.hidden { .doc-nav .content.hidden {
display: flex; display: flex;
} }
.doc-container {
.doc-container { margin-top: 0;
margin-top: 0; margin-left: 300px;
margin-left: 300px; }
} .doc-toc {
top: 0;
.doc-toc { }
top: 0; }
}
}

View File

@ -7,8 +7,43 @@ import os
import os.cmdline import os.cmdline
import strings import strings
import v.doc import v.doc
import v.scanner
import v.table
import v.token
import v.vmod import v.vmod
enum HighlightTokenTyp {
unone
atrule
attr_name
bold
boolean
builtin
char
comment
constant
cdata
deleted
doctype
entity
function
important
inserted
italic
keyword
name
number
operator
prolog
property
punctuation
selector
string
symbol
tag
url
}
const ( const (
allowed_formats = ['md', 'markdown', 'json', 'text', 'stdout', 'html', 'htm'] allowed_formats = ['md', 'markdown', 'json', 'text', 'stdout', 'html', 'htm']
exe_path = os.executable() exe_path = os.executable()
@ -131,32 +166,98 @@ fn (cfg DocConfig) gen_json(idx int) string {
return jw.str() return jw.str()
} }
fn html_highlight(code string, tb &table.Table) string {
builtin := ['bool', 'string', 'i8', 'i16', 'int', 'i64', 'i128', 'byte', 'u16', 'u32', 'u64', 'u128', 'rune', 'f32', 'f64', 'any_int', 'any_float', 'byteptr', 'voidptr', 'any']
highlight_code := fn (tok token.Token, typ HighlightTokenTyp) string {
lit := if typ in [.unone, .operator] { tok.kind.str() } else { tok.lit }
return if typ in [.unone, .name] { lit } else { '<span class="token $typ">$lit</span>' }
}
s := scanner.new_scanner(code, .parse_comments)
mut tok := s.scan()
mut next_tok := s.scan()
mut buf := strings.new_builder(200)
mut i := 0
for i < code.len {
if i == tok.pos {
mut tok_typ := HighlightTokenTyp.unone
match tok.kind {
.name {
if tok.lit in builtin {
tok_typ = .builtin
} else if next_tok.kind in [.lcbr, .lpar] {
tok_typ = .symbol
} else {
tok_typ = .name
}
}
.comment {
tok_typ = .comment
}
.chartoken {
tok_typ = .char
}
.string {
tok_typ = .string
}
.number {
tok_typ = .number
}
.key_true,
.key_false {
tok_typ = .boolean
}
else {
if token.is_key(tok.lit) || token.is_decl(tok.kind) {
tok_typ = .keyword
} else if tok.kind == .decl_assign || tok.kind.is_assign() || tok.is_unary() || tok.kind.is_relational() || tok.kind.is_infix() {
tok_typ = .operator
}
}
}
buf.write(highlight_code(tok, tok_typ))
if next_tok.kind != .eof {
i = tok.pos + tok.len
tok = next_tok
next_tok = s.scan()
} else {
break
}
} else {
buf.write_b(code[i])
i++
}
}
return buf.str()
}
fn doc_node_html(dd doc.DocNode, link string, head bool, tb &table.Table) string {
mut dnw := strings.new_builder(200)
link_svg := '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></svg>'
head_tag := if head { 'h1' } else { 'h2' }
md_content := markdown.to_html(dd.comment)
hlighted_code := html_highlight(dd.content, tb)
dnw.writeln('<section id="${slug(dd.name)}" class="doc-node">')
if dd.name != 'README' {
dnw.write('<div class="title"><$head_tag>${dd.name} <a href="#${slug(dd.name)}">#</a></$head_tag>')
if link.len != 0 {
dnw.write('<a class="link" target="_blank" href="$link">$link_svg</a>')
}
dnw.write('</div>')
}
if head {
dnw.write(md_content)
} else {
dnw.writeln('<pre class="signature language-v"><code class="language-v">$hlighted_code</code></pre>')
dnw.writeln(md_content)
}
dnw.writeln('</section>')
return dnw.str()
}
fn (cfg DocConfig) gen_html(idx int) string { fn (cfg DocConfig) gen_html(idx int) string {
dcs := cfg.docs[idx] dcs := cfg.docs[idx]
mut hw := strings.new_builder(200) mut hw := strings.new_builder(200)
mut toc := strings.new_builder(200) 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 := '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></svg>'
head_tag := if head { 'h1' } else { 'h2' }
md_content := markdown.to_html(dd.comment)
dnw.writeln('<section id="${slug(dd.name)}" class="doc-node">')
if dd.name != 'README' {
dnw.write('<div class="title"><$head_tag>${dd.name} <a href="#${slug(dd.name)}">#</a></$head_tag>')
if link.len != 0 {
dnw.write('<a class="link" target="_blank" href="$link">$link_svg</a>')
}
dnw.write('</div>')
}
if head {
dnw.write(md_content)
} else {
dnw.writeln('<pre class="signature"><code class="language-v">${dd.content}</code></pre>')
dnw.writeln(md_content)
}
dnw.writeln('</section>')
return dnw.str()
}
// generate toc first // generate toc first
for cn in dcs.contents { for cn in dcs.contents {
if cn.parent_type !in ['void', ''] { continue } if cn.parent_type !in ['void', ''] { continue }
@ -179,7 +280,6 @@ 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)
v_prism_js := cfg.get_resource('v-prism.js', false)
v_prism_css := cfg.get_resource('v-prism.css', true) v_prism_css := cfg.get_resource('v-prism.css', true)
hw.write(' hw.write('
@ -189,16 +289,14 @@ fn (cfg DocConfig) gen_html(idx int) string {
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge" /> <meta http-equiv="x-ua-compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${dcs.head.name} | vdoc</title> <title>${dcs.head.name} | vdoc</title>')
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Source+Code+Pro:wght@500&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="https://necolas.github.io/normalize.css/8.0.1/normalize.css" />')
// write css // write css
if cfg.inline_assets { if cfg.inline_assets {
hw.write('<style>$v_prism_css</style>') hw.write('\n <style>$v_prism_css</style>')
hw.write('<style>$doc_css_min</style>') hw.write('\n <style>$doc_css_min</style>')
} else { } else {
hw.write('\n <link rel="stylesheet" href="$v_prism_css" />') hw.write('\n <link rel="stylesheet" href="$v_prism_css" />')
hw.write('\n <link rel="stylesheet" href="$doc_css_min" />') hw.write('\n <link rel="stylesheet" href="$doc_css_min" />')
} }
@ -266,19 +364,19 @@ fn (cfg DocConfig) gen_html(idx int) string {
} }
hw.write('</ul>\n</nav>\n</header>') hw.write('</ul>\n</nav>\n</header>')
hw.write('<div class="doc-container">\n<div class="doc-content">\n') hw.write('<div class="doc-container">\n<div class="doc-content">\n')
hw.write(doc_node_html(dcs.head, '', true)) hw.write(doc_node_html(dcs.head, '', true, dcs.table))
for cn in dcs.contents { for cn in dcs.contents {
if cn.parent_type !in ['void', ''] { continue } if cn.parent_type !in ['void', ''] { continue }
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 := cn.file_path.replace('$base_dir/', '')
hw.write(doc_node_html(cn, get_src_link(cfg.manifest.repo_url, file_path_name, cn.pos.line), false)) hw.write(doc_node_html(cn, get_src_link(cfg.manifest.repo_url, file_path_name, cn.pos.line), false, dcs.table))
children := dcs.contents.find_children_of(cn.name) children := dcs.contents.find_children_of(cn.name)
if children.len != 0 { if children.len != 0 {
for child in children { for child in children {
child_file_path_name := child.file_path.replace('$base_dir/', '') child_file_path_name := child.file_path.replace('$base_dir/', '')
hw.write(doc_node_html(child, get_src_link(cfg.manifest.repo_url, child_file_path_name, child.pos.line), false)) hw.write(doc_node_html(child, get_src_link(cfg.manifest.repo_url, child_file_path_name, child.pos.line), false, dcs.table))
} }
} }
} }
@ -287,14 +385,10 @@ fn (cfg DocConfig) gen_html(idx int) string {
hw.write('<div class="doc-toc">\n\n<ul>\n${toc.str()}</ul>\n</div>') hw.write('<div class="doc-toc">\n\n<ul>\n${toc.str()}</ul>\n</div>')
} }
hw.write('</div></div>') hw.write('</div></div>')
hw.write('<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/components/prism-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/components/prism-clike.min.js"></script>')
if cfg.inline_assets { if cfg.inline_assets {
hw.write('<script>$doc_js_min</script>') hw.write('<script>$doc_js_min</script>')
hw.write('<script>$v_prism_js</script>')
} else { } else {
hw.write('<script src="$doc_js_min"></script>') hw.write('<script src="$doc_js_min"></script>')
hw.write('<script src="$v_prism_js"></script>')
} }
hw.write('</body> hw.write('</body>
</html>') </html>')