├── CNAME ├── favicon.ico ├── README.md ├── static ├── img │ └── logo.svg ├── js │ └── index.js └── css │ └── index.css ├── installation.html ├── index.html ├── custom-components.html ├── scripting.html ├── configuration.html └── theming.html /CNAME: -------------------------------------------------------------------------------- 1 | godocument.dev -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phillip-England/godocument.dev/main/favicon.ico -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Godocument 2 | 3 | ## Documentation 4 | 5 | To read the full documentation, check out [godocument.dev](https://godocument.dev) 6 | 7 | 8 | 9 | 10 | # Introduction 11 | 12 | ## What is Godocument? 13 | Godocument is a static site generator inspired by [Docusaurus](https://docusaurus.io/) and powered by [Htmx](https://htmx.org). Documenting your code should be *simple*. 14 | 15 | Godocument requires Go version 1.22.0 or greater 16 | 17 | ## Hello, World 18 | 19 | 20 | A Godocument website can be created using the following steps: 21 | 22 | 23 | - Make a directory 24 | 25 | ```bash 26 | mkdir 27 | cd 28 | ``` 29 | 30 | - Clone the repo 31 | 32 | ```bash 33 | git clone https://github.com/phillip-england/godocument . 34 | ``` 35 | 36 | - Reset the project 37 | 38 | ```bash 39 | go run main.go --reset 40 | ``` 41 | 42 | - Add some new entries to `godocument.config.json`: 43 | 44 | ```json 45 | { 46 | "docs": { 47 | "Introduction": "/introduction.md", 48 | "First Page": "/first-page.md", 49 | "First Section": { 50 | "Second Page": "/first-section/second-page.md" 51 | } 52 | }, 53 | "meta": { 54 | "title": "My Website" 55 | } 56 | } 57 | ``` 58 | 59 | - Inside of `/docs`, create `first-page.md` 60 | 61 | ```bash 62 | touch /docs/first-page.md 63 | ``` 64 | 65 | - Add the following lines to `/docs/first-page.md` 66 | 67 | ```md 68 | 69 | 70 | # First Page 71 | 72 | ## Hello, World 73 | 74 | This is the first page I've created using Godocument! 75 | ``` 76 | 77 | - Inside of `/docs` create a directory called `/first-section` 78 | 79 | ```bash 80 | mkdir /docs/first-section 81 | ``` 82 | 83 | - Inside of `/docs/first-section`, create a file called `second-page.md` 84 | 85 | ```bash 86 | touch /docs/first-section/second-page.md 87 | ``` 88 | 89 | - Add the following lines to `/docs/first-section/second-page.md` 90 | 91 | ```md 92 | 93 | 94 | # Second Page 95 | 96 | ## Hello, World 97 | 98 | This is the second page I've created using Godocument! 99 | ``` 100 | 101 | - From your application's root directory, run the following command to view the results on `localhost:8080`: 102 | 103 | ```bash 104 | go run main.go 105 | ``` 106 | 107 | - To test your static assets locally, run: 108 | 109 | ```bash 110 | go run main.go --build 111 | ``` 112 | 113 | - To build for production, run: 114 | 115 | ```bash 116 | go run main.go --build 117 | ``` 118 | 119 | That's it! Your example is deployment-ready and can be found at `/out`. You can easily deploy on Github Pages, Amazon S3, or a CDN of your choice. -------------------------------------------------------------------------------- /static/img/logo.svg: -------------------------------------------------------------------------------- 1 | Godocument -------------------------------------------------------------------------------- /installation.html: -------------------------------------------------------------------------------- 1 | Godocument - Installation 2 |

Installation

The Repo

You can find a blank Godocument template at https://github.com/phillip-england/godocument.

All the commands in this guide assume you are using a Unix-based terminal.

To get started, create a directory and clone the repo within it:

mkdir <your-app-name>
3 | cd <your-app-name>
4 | git clone https://github.com/phillip-england/godocument .
5 | 
-------------------------------------------------------------------------------- /static/js/index.js: -------------------------------------------------------------------------------- 1 | (()=>{let i=!1;if(localStorage.getItem("popstate")=="true"&&(i=!0,document.getElementsByTagName("html")[0].setAttribute("loaded","false")),document.getElementsByTagName("html")[0].getAttribute("loaded")=="false"){function e(e,t){return e||console.error("Root is not defined in qs()"),e.querySelector(t)}function n(e,t){return e||console.error("Root is not defined in qsa()"),e.querySelectorAll(t)}function o(e,t,n){if(e){if(e==t)return;let s=n(e);if(s==!0)return;o(e.parentNode,t,n)}}function t(e,t,n){e.removeEventListener(t,n),e.addEventListener(t,n)}function a(){localStorage.setItem("popstate","true")}function r(){localStorage.setItem("popstate","false")}class l{getState(e,t){return e.getAttribute("zez:"+t).split(" ")}applyState(e,t){let n=this.getState(e,t);for(let t=0;t-1&&n.splice(t,1)}e.classList=n.join(" ")}containsState(e,t){let n=this.getState(e,t),s=Array.from(e.classList);for(let e=0;e{if(e.tagName=="LI")return n=e,!0});let s=e(n,"ul"),i=e(n,"div");c.toggleStateAll([i,s],"active")}setActiveNavItem(){for(let t=0;t{if(t.classList.contains("dropdown")){let n=e(t,"ul"),s=e(t,"div"),o=e(t,"summary");c.applyStateAll([o,s,n],"active")}}))}}}class u{constructor(e,t,n){this.pagenav=e,this.pagenavLinks=t,this.articleTitles=n,this.windowTimeout=null,this.bufferZone=200,this.activeLink=null,this.hook()}hook(){this.setActivePageNavItem(),t(window,"scroll",this.handleWindowScroll.bind(this))}setActivePageNavItem(){if(this.pagenavLinks.length==0||this.articleTitles.length==0)return;for(let e=0;e0){this.activeLink=t;break}if(e==this.articleTitles.length-1&&n<0){this.activeLink=t;break}if(n<0&&o>0){if(o{this.setActivePageNavItem()},100)}}class h{constructor(e,t,n){this.headerBars=e,this.overlay=t,this.sitenav=n,this.hook()}hook(){t(this.headerBars,"click",this.toggleMobileNav.bind(this)),t(this.overlay,"click",this.toggleMobileNav.bind(this)),this.closeMobileNav()}toggleMobileNav(){c.toggleState(this.overlay,"active"),c.toggleState(this.sitenav,"active")}closeMobileNav(){c.removeState(this.overlay,"active"),c.removeState(this.sitenav,"active")}}class m{constructor(e,t,n){this.sunIcons=e,this.moonIcons=t,this.htmlDocument=n,this.hook()}hook(){this.initTheme();for(let e=0;e"+e.slice(t+1),t++;t"+e.slice(t+1)}return e}registerComponent(e,t){let n=document.getElementsByClassName(e);for(let e=0;e 3 | 4 | 5 | 8 | 9 |

Important

10 |
11 |

{text}

12 | 13 | `)}}class g{constructor(e){e.registerComponent("md-warning",` 14 |
15 | 16 | 17 | 21 | 22 | 23 |

Warning

24 |
25 |

{text}

26 |
27 | `)}}class v{constructor(e){e.registerComponent("md-correct",` 28 |
29 | 30 | 31 | 34 | 35 |

Correct

36 |
37 |

{text}

38 |
39 | `)}}function s(t){if(t.type=="popstate"){c.removeState(document.getElementsByTagName("body")[0],"loaded"),a();return}const y=e(document,"body"),s=e(document,"#sitenav"),x=n(s,".item"),w=n(s,".dropdown"),o=e(document,"#pagenav"),j=n(o,"a"),b=e(document,"#article"),_=n(b,"h2, h3, h4, h5, h6"),l=e(document,"#header"),O=e(l,"#bars"),r=e(document,"#overlay"),C=n(document,".sun"),E=n(document,".moon"),k=e(document,"html");if(window.scrollTo(0,0,{behavior:"auto"}),new d(s,x,w,l,r),new u(o,j,_),new h(O,r,s),new m(C,E,k),!i){let e=new f;new p(e),new g(e),new v(e)}Prism.highlightAll(),c.applyState(y,"loaded"),document.getElementsByTagName("html")[0].setAttribute("loaded","true")}localStorage.getItem("popstate")=="true"?(r(),s({type:"DOMContentLoaded"})):(t(window,"popstate",s),t(window,"DOMContentLoaded",s),t(document.getElementsByTagName("body")[0],"htmx:afterOnLoad",s))}})() -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | Godocument - Introduction 2 |

Introduction

What is Godocument?

Godocument is a static site generator inspired by Docusaurus and powered by Htmx. Documenting your code should be simple.

Godocument requires Go version 1.22.0 or greater

Hello, World

A Godocument website can be created using the following steps:

  • Make a directory
mkdir <your-apps-name>
 3 | cd <your-apps-name>
 4 | 
  • Clone the repo
git clone https://github.com/phillip-england/godocument .
 5 | 
  • Reset the project
go run main.go --reset
 6 | 
  • Add some new entries to godocument.config.json:
{
 7 |     "docs": {
 8 |         "Introduction": "/introduction.md",
 9 |         "First Page": "/first-page.md",
10 |         "First Section": {
11 |             "Second Page": "/first-section/second-page.md"
12 |         }
13 |     },
14 |     "meta": {
15 |         "title": "My Website"
16 |     }
17 | }
18 | 
  • Inside of /docs, create first-page.md
touch /docs/first-page.md
19 | 
  • Add the following lines to /docs/first-page.md
<meta name="description" content="Explore my first page with Godocument"></meta>
20 | 
21 | # First Page
22 | 
23 | ## Hello, World
24 | 
25 | This is the first page I've created using Godocument!
26 | 
  • Inside of /docs create a directory called /first-section
mkdir /docs/first-section
27 | 
  • Inside of /docs/first-section, create a file called second-page.md
touch /docs/first-section/second-page.md
28 | 
  • Add the following lines to /docs/first-section/second-page.md
<meta name="description" content="Explore my second page with Godocument"></meta>
29 | 
30 | # Second Page
31 | 
32 | ## Hello, World
33 | 
34 | This is the second page I've created using Godocument!
35 | 
  • From your application's root directory, run the following command to view the results on localhost:8080:
go run main.go
36 | 
  • To test your static assets locally, run:
go run main.go --build
37 | 

-- To build for production, run:

go run main.go --build <your-server-url>
38 | 

That's it! Your example is deployment-ready and can be found at /out. You can easily deploy on Github Pages, Amazon S3, or a CDN of your choice.

-------------------------------------------------------------------------------- /custom-components.html: -------------------------------------------------------------------------------- 1 | Godocument - Custom Components 2 |

Custom Components

Creating a New Component

All Javascript for Godocument is located in /static/js/index.js.

To create a new custom component, first create a class to represent the component.

Let's call this component, simple-component. The constructor should take in a parameter called customComponent, which will be an object built from the CustomComponent class.

The CustomComponent class is already included in Godocument.

class SimpleComponent {
 3 |     constructor(customComponent) {
 4 | 
 5 |     }
 6 | }
 7 | 

In onLoad(), be sure to instantiate both CustomComponent and SimpleComponent:

function onLoad() {
 8 |     // ...
 9 | 
10 |     // defining custom components
11 |     let customComponents = new CustomComponent()
12 |     new SimpleComponent(customComponents)
13 | }
14 | 

In the constructor of SimpleComponent call customComponent.registerComponent(className, htmlContent) as follows:

class SimpleComponent {
15 |     constructor(customComponent) {
16 |         customComponent.registerComponent("simple-component", `
17 |             <div>
18 |                 <h1>Hello, World</h1>
19 |                 <p>{text}</p>
20 |             </div>
21 |         `)
22 |     }
23 | }
24 | 

Take note of this line:

<p>{text}</p>
25 | 

Register component will replace {text} with the innerHTML of the component.

To utilize simple-component, place the following markup in any of your .md files:

<span class='simple-component'>I am a simple component!</span>
26 | 

Included Components

Godocument comes with a few components already built. Here they are:

MdImportant

I am created by using this markup in a .md file: <span class='md-important'>I am important!</span>

MdWarning

I am created by using this markup in a .md file: <span class='md-warning'>I am a warning!</span>

MdCorrect

I am created by using this markup in a .md file: <span class='md-correct'>That is correct!</span>

Goldmark html.WithUnsafe

Since we are using Goldmark to convert .md files into workable HTML, we have to use the html.WithUnsafe() renderer option when instantiating Goldmark in our project. This will allow us to place HTML elements directly in our .md files.

This is only considered unsafe if the content within our .md files is controlled by our users. In our case, since we will be the ones writing the markup directly, it is not considered unsafe.

Removing html.WithUnsafe() from Goldmark's rendering options will cause Goldmark to ignore any HTML markup within our .md files.

-------------------------------------------------------------------------------- /scripting.html: -------------------------------------------------------------------------------- 1 | Godocument - Scripting 2 |

Scripting

Single Page Application

Godocument uses Htmx to provide a single page application user experience. Htmx enables us to do this without the complexity of a Javascript framework.

This functionality is enabled by a single attribute on our <body> tag, hx-boost.

<body hx-boost='true' ...>
 3 | 

Basically, when you click on a navigational link within your website, Htmx will take over and the following will happen:

  1. An AJAX request will be sent to the href of the clicked <a>.
  2. When the response is received, the <body> from the response will be isolated.
  3. Our page's current <body> will be replaced with the newly received <body>.

All of this will be done without a full-page refresh. Since we are generating static pages, the wait time between when a request is clicked and when the response is receieved will be minimal, giving the illusion of a single page experience to the user.

Htmx Implications

Using Htmx's hx-boost attribute has implications on how we need to think about using Javascript in our application.

Since the <body> is the only thing changed when using hx-boost, the Javascript located in the <head> of our document will only be loaded once. However, Javascript located in the <body> will be ran on each request.

This can create issues when declaring functions, declaring variables, and mounting event listeners.

loaded attribute

Godocument makes use of an attribute, loaded, on the <html> tag to avoid reinstantiating variables multiple times.

<html lang="en" loaded="false" ..>
 4 | 

After the page is loaded on the initial visit, this attribute is set to true. This will prevent our variables and functions from being instantiated more than once.

Failing to set loaded="true" on <html> will result in unexpected behavior

onLoad function

Godocument makes use of the function onLoad() to run the appropriate Javascript on all page loads.

function onLoad() {
 5 | 
 6 |     // elements
 7 |     const body = qs(document, 'body')
 8 |     const sitenav = qs(document, '#sitenav')
 9 |     const sitenavItems = qsa(sitenav, '.item')
10 |     const sitenavDropdowns = qsa(sitenav, '.dropdown')
11 |     const pagenav = qs(document, '#pagenav')
12 |     const pagenavLinks = qsa(pagenav, 'a')
13 |     const article = qs(document, '#article')
14 |     const articleTitles = qsa(article, 'h2, h3, h4, h5, h6')
15 |     const header = qs(document, '#header')
16 |     const headerBars = qs(header, '#bars')
17 |     const overlay = qs(document, '#overlay')
18 |     const sunIcons = qsa(document, '.sun')
19 |     const moonIcons = qsa(document, '.moon')
20 |     const htmlDocument = qs(document, 'html')
21 | 
22 |     // hooking events and running initializations
23 |     window.scrollTo(0, 0, { behavior: 'auto' })
24 |     new SiteNav(sitenav, sitenavItems, sitenavDropdowns, header, overlay)
25 |     new PageNav(pagenav, pagenavLinks, articleTitles)
26 |     new Header(headerBars, overlay, sitenav)
27 |     new Theme(sunIcons, moonIcons, htmlDocument)
28 | 
29 |     // web components
30 |     doOnce(() => {
31 |         customElements.define('md-important', MdImportant)
32 |         customElements.define('md-warning', MdWarning)
33 |         customElements.define('md-correct', MdCorrect)
34 |     })
35 | 
36 |     // init
37 |     Prism.highlightAll();
38 | 
39 |     // reveal body
40 |     zez.applyState(body, 'loaded')
41 | 
42 | }
43 | 

onLoad() is mounted to the window and <body> using the DOMContentLoaded and htmx:afterOnLoad events. Click here to read more about Htmx events.

eReset(window, 'DOMContentLoaded', onLoad) // initial page load
44 | eReset(document.getElementsByTagName('body')[0], "htmx:afterOnLoad", onLoad) // after htmx swaps
45 | 

DOMContentLoaded will handle the initial page load, while hmtx:afterOnLoad will handle all other navigations.

Managing Events

Since the page is never refreshed using Htmx, we need to make sure we are unmounting events and remounting them on every navigation. eReset() is a handy function that does just that.

function eReset(node, eventType, callback) {
46 |     node.removeEventListener(eventType, callback)
47 |     node.addEventListener(eventType, callback)
48 | }
49 | 

Instead of calling element.addEventListener(), it is better to use eReset() to ensure events are properly managed between page navigations.

Failing to unhook events upon navigation will result in the same events being hooked multiple times to the target element, which can have unexpected consequences and lead to poor memory management.

-------------------------------------------------------------------------------- /configuration.html: -------------------------------------------------------------------------------- 1 | Godocument - Configuration 2 |

Configuration

godocument.config.json

godocument.config.json is the configuration file for your application. It contains the necessary information to generate your website's routes.

The order of items in godocument.config.json will determine the order of your pages in your website.

Here is the base configuration needed to generate a site using Godocument:

{
 3 |     "docs": {
 4 |         "Introduction": "/introduction.md"
 5 |     }
 6 | }
 7 | 

The /docs directory and the /docs/introduction.md file are required for Godocument. Also, the json object "docs" must be named "docs" and the first entry beneath "docs" must be "Introduction": "/introduction.md". Failing to meet these requirements will result in a panic.

Pages

The entries in godocument.config.json can either be pages or sections. Let's start with pages.

To denote a page, simply create a key-value pair with the key being the name of the page and the value being the file path to the .md file for the page. You can name pages whatever you would like.

All file paths in godocument.config.json are relative to /docs. This means you do not have to the include /docs in your file paths as Godocument assumes all your markdown files are in /docs.

Here is how you would add a new page to the base configuration:

{
 8 |     "docs": {
 9 |         "Introduction": "/introduction.md",
10 |         "New Page": "/new-page.md"
11 |     }
12 | }
13 | 

After adding the page to godocument.config.json you will need to create the associated file. From the root of your application, run:

touch /docs/new-page.md
14 | 

Then, add the following lines to /docs/new-page.md:

# New Page
15 | 
16 | I created a new page using Godocument!
17 | 

From the root of your application, run go run main.go and view the results at localhost:8080.

Sections

Sections are named areas of your website which contain a series of pages. Sections can also contain sub-sections. In godocument.config.json, a section can be denoted by creating an object. For example:

{
18 |     "docs": {
19 |         "Introduction": "/introduction.md",
20 |         "New Section": {
21 |             
22 |         }
23 |     }
24 | }
25 | 

After creating a section, you can add pages within it:

{
26 |     "docs": {
27 |         "Introduction": "/introduction.md",
28 |         "New Section": {
29 |             "About": "/new-section/about.md" 
30 |         }
31 |     }
32 | }
33 | 

You can also add sub-sections:

{
34 |     "docs": {
35 |         "Introduction": "/introduction.md",
36 |         "New Section": {
37 |             "About": "/new-section/about.md",
38 |             "More Info": {
39 |                 "Origins": "/new-section/more-info/origins.md"
40 |             }
41 |         }
42 |     }
43 | }
44 | 

Create the corresponding files and directories:

mkdir /docs/new-section
45 | touch /docs/new-section/about.md
46 | mkdir /docs/new-section/more-info
47 | touch /docs/new-section/more-info/origins.md
48 | 

Add the following content to /docs/new-section/about.md

# About
49 | 
50 | I created a page within a section using Godocument!
51 | 

Then, add the following lines to /docs/new-section/more-info/origin.md:

# Origins
52 | 
53 | I created a page within a sub-section using Godocument!
54 | 

To test the results, run go run main.go from the root of your application and visit localhost:8080

/docs structure

Godocument does not require you to structure your /docs directory in any particular way, BUT it is highly recommended to have your /docs directory mirror the structure of your godocument.config.json file.

For example, here is a godocument.config.json file which does not follow the proper conventions.

The example below does not follow the recommended conventions for godocument.config.json.

{
55 |     "docs":{
56 |         "Introduction": "/introduction.md",
57 |         "More Info": {
58 |             "About": "/about.md"
59 |         }
60 |     }
61 | }
62 | 

It does not follow the conventions because /about.md should have a file path which mirrors the structure of godocument.config.json.

To correct the above godocument.config.json make the changes below.

{
63 |     "docs": {
64 |         ...
65 |         "More Info": {
66 |             "About": "/more-info/about.md"
67 |         }
68 |     }
69 | }
70 | 

Such a change will ensure that the /docs directory mirrors the structure of godocument.config.json, as recommended.

Customizing Titles

Godocument autogenerates titles based off the keys provided in the "docs" section of godocument.config.json. For example, a key value pair of "Introduction": "/introduction.md" would render a title of Godocument - Introduction when visiting the introduction page.

All pags titles will be prefixed with "Godocument - " until you specify otherwise in the "meta" section of godocument.config.json.

To modify title prefixes, set the following config:

{
71 |     ... your "docs" section,
72 |     "meta": {
73 |         "title": "Custom Title Prefix"
74 |     }
75 | }
76 | 

Doing this will prefix all autogenerated titles with, Custom Title Prefix - .

Hot Reloading

Air is a binary that provides hot-reloading functionality. It can be installed using:

go install github.com/cosmtrek/air@latest
77 | 

Just be sure your Go binaries are registered in your $PATH.

All the configuration needed to implment Air properly in Godocument is included in .air.toml.

When running Air, a /tmp directory will be generated. /tmp is already included in your .gitignore and you can disregard it during development.

To enable hot-reloading, go to the root of your project and run:

air
78 | 
-------------------------------------------------------------------------------- /theming.html: -------------------------------------------------------------------------------- 1 | Godocument - Theming 2 |

Theming

Code Blocks

Code blocks are made possible by Prism.

Godocument includes support for all languages supported by Prism. This is to make it easy to get started with your website. However, when you plan to deploy, it is a good idea to go over to Prism's download page and select only the languages used in your application.

When downloading the required languages for your site, you only need to download the .js file and replace /static/js/prism.js with the newly downloaded file. Be sure the file is named, primsm.js.

CSS Usage

Godocument uses both Vanilla CSS and Tailwind for styling. If you intend to make changes to the Tailwind classes in your markup, you will need to download the Tailwind binary and run tailwindcss -i './static/css/input.css' -o './static/css/output.css' from the root of your project. Doing so will recompile your /static/css/output.css and adjust to any changes.

The tailwind.config.json file provided in the Godocument repo will contain the proper configuration needed to target all the .html and .go files in your project.

Vanilla CSS is used in Godocument for things like the page layout, scrollbar appearance, and a few other things. All Vanilla CSS can be found at /static/css/index.css.

CSS Variables

Godocument makes use of CSS variables to give users more control of their theme. Variables are either viewed as utility variables or element-specific variables.

To adjust the theming for your site, edit the variables found at the top of /static/css/index.css.

Utility Variables

Utility variables are not directly used in markup. Rather, they are intended to be used in element-specific variables. Here are the color utility variables for this site:

--white: #fafafa;
 3 | --black: #1f1f1f;
 4 | --gray-800: #333333;
 5 | --gray-700: #555555;
 6 | --gray-600: #777777;
 7 | --gray-500: #999999;
 8 | --gray-400: #bbbbbb;
 9 | --gray-300: #dddddd;
10 | --gray-200: #f0f0f0;
11 | --gray-100: #f5f5f5;
12 | --light-gray: #d0d0d0;
13 | --gray: #555555;
14 | --darkest-gray: #222222;
15 | --purple: #ba8ef7;
16 | --dark-purple: #712fec;
17 | --green: #3bec74;
18 | --dark-green: #057d2f;
19 | --pink: #b370b1;
20 | --yellow: #ffea6b;
21 | --dark-yellow: #7f7108;
22 | --orange: #ffa763;
23 | --dark-orange: #c64719;
24 | --blue: #2494da;
25 | --dark-blue: #1b6dbf;
26 | --red: #ff4d3f;
27 | --dark-red: #c82216;
28 | 

Element-Specific Variables

Element-specific variables make use of utility variables. Here are the element-specific variables that control the colors in the codeblocks found on this site:

/* light code blocks */
29 | --code-bg-color: var(--gray-200);
30 | --code-token-property: var(--dark-purple);
31 | --code-string: var(--dark-green);
32 | --code-token-selector: var(--dark-orange);
33 | --code-function: var(--dark-yellow);
34 | --code-keyword: var(--dark-purple);
35 | --code-operator: var(--black);
36 | --code-punctuation: var(--gray-700);
37 | --code-important: var(--dark-orange);
38 | --code-comment: var(--gray-700);
39 | 
40 | /* dark code blocks */
41 | --dark-code-bg-color: var(--gray-800);
42 | --dark-code-token-property: var(--purple);
43 | --dark-code-string: var(--green);
44 | --dark-code-token-selector: var(--orange);
45 | --dark-code-function: var(--yellow);
46 | --dark-code-keyword: var(--purple);
47 | --dark-code-operator: var(--white);
48 | --dark-code-punctuation: var(--gray-300);
49 | --dark-code-comment: var(--gray-300)
50 | 

Variables in Tailwind

Godocument makes use of Tailwind's ability to use CSS variables within Tailwind classes. For example, here is the markup for the <header> at the top of this page:

<header id="header" class="flex flex-row justify-between items-center border-b z-30 p-4 sticky top-0 w-full bg-[var(--header-bg-color)] dark:bg-[var(--dark-header-bg-color)] border-[var(--b-color)] dark:border-[var(--dark-b-color)]" style="grid-area: header;">
51 |     <div class="header-logo-wrapper flex flex-row shrink-0 items-center w-[250px]">
52 |         <img class="logo items-center flex-row" src="/static/img/logo.svg" alt="logo" id="logo">
53 |     </div>
54 |     <svg class="sun cursor-pointer hidden lg:block shrink-0 dark:lg:hidden" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
55 |         <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 5V3m0 18v-2M7.05 7.05 5.636 5.636m12.728 12.728L16.95 16.95M5 12H3m18 0h-2M7.05 16.95l-1.414 1.414M18.364 5.636 16.95 7.05M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z"/>
56 |     </svg>
57 |     <svg class="moon cursor-pointer hidden shrink-0 dark:lg:block" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
58 |         <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 21a9 9 0 0 1-.5-17.986V3c-.354.966-.5 1.911-.5 3a9 9 0 0 0 9 9c.239 0 .254.018.488 0A9.004 9.004 0 0 1 12 21Z"/>
59 |     </svg>      
60 |     <svg id="bars" class="cursor-pointer block lg:hidden shrink-0" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="none" viewBox="0 0 24 24">
61 |         <path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M5 7h14M5 12h14M5 17h14"/>
62 |     </svg>
63 | </header>
64 | 

Take note of the classes on the <header> element itself. You'll see classes such as bg-[var(--header-bg-color)] or dark:border-[var(--dark-b-color)].

Although the syntax is ugly, it does come with its perks.

You can adjust the colors of the elements on the page using variables instead of having to change the markup for each individual element.

Styling Markdown Content

Markdown content is styled using Vanilla CSS. This is done to minimize the amount of text found in .md files. To adjust the styling of markdown content, edit the // markdown styles ------ section of /static/css/index.css.

To change the logo for your site, simply replace /static/img/logo.svg with your logo. There is only one caveat, logos with a large height may shift the navbar in unexpected ways. For this reason, it is recommended to use a logo which is wide, not tall.

favicon.ico

During development, the server searches for your favicon.ico at /favicon.ico. When you go to build your static assest, the favicon will be placed in /out/favicon.ico. To change your favicon.ico, simply replace the icon found at /favicon.ico.

-------------------------------------------------------------------------------- /static/css/index.css: -------------------------------------------------------------------------------- 1 | html{scroll-padding-top:75px}:root{--text-base:16px;--text-2xs:0.75rem;--text-xs:1rem;--text-sm:1.25rem;--text-md:1.5rem;--text-lg:1.75rem;--text-xl:2rem;--text-2xl:3rem;--rounded-sm:0.25rem;--rounded-md:0.5rem;--white:#fafafa;--black:#1f1f1f;--gray-800:#333333;--gray-700:#555555;--gray-600:#777777;--gray-500:#999999;--gray-400:#bbbbbb;--gray-300:#dddddd;--gray-200:#f0f0f0;--gray-100:#f5f5f5;--light-gray:#d0d0d0;--gray:#555555;--darkest-gray:#222222;--purple:#ba8ef7;--dark-purple:#712fec;--green:#3bec74;--dark-green:#057d2f;--pink:#b370b1;--yellow:#ffea6b;--dark-yellow:#7f7108;--orange:#ffa763;--dark-orange:#c64719;--blue:#2494da;--dark-blue:#1b6dbf;--red:#ff4d3f;--dark-red:#c82216;--b-color:var(--gray-300);--dark-b-color:var(--gray-800);--b-hover-color:var(--gray-400);--dark-b-hover-color:var(--gray);--default-text-color:var(--black);--dark-default-text-color:var(--white);--text-important:var(--dark-blue);--dark-text-important:var(--blue);--default-bg-color:var(--white);--dark-default-bg-color:var(--black);--bg-hover-color:var(--gray-200);--dark-bg-hover-color:var(--gray-800);--header-bg-color:var(--white);--dark-header-bg-color:var(--black);--footer-bg-color:var(--white);--dark-footer-bg-color:var(--black);--overlay-bg-color:var(--black);--sitenav-bg-color:var(--white);--dark-sitenav-bg-color:var(--black);--pagenav-bg-color:var(--white);--dark-pagenav-bg-color:var(--black);--scroll-thumb-light:var(--gray-400);--scroll-thumb-dark:var(--gray-800);--md-h1-size:var(--text-2xl);--md-h2-size:var(--text-xl);--md-h3-size:var(--text-lg);--md-h4-size:var(--text-md);--md-h5-size:var(--text-sm);--md-h6-size:var(--text-xs);--md-p-size:var(--text-xs);--inline-code-b-radius:var(--rounded-sm);--inline-code-bg-color:var(--gray-200);--inline-code-web-component-bg-color:var(--gray-300);--dark-inline-code-web-component-bg-color:var(--gray-700);--dark-inline-code-bg-color:var(--gray-800);--code-b-radius:var(--rounded-sm);--code-bg-color:var(--gray-200);--code-token-property:var(--dark-purple);--code-string:var(--dark-green);--code-token-selector:var(--dark-orange);--code-function:var(--dark-yellow);--code-keyword:var(--dark-purple);--code-operator:var(--black);--code-punctuation:var(--gray-700);--code-important:var(--dark-orange);--code-comment:var(--gray-700);--dark-code-bg-color:var(--gray-800);--dark-code-token-property:var(--purple);--dark-code-string:var(--green);--dark-code-token-selector:var(--orange);--dark-code-function:var(--yellow);--dark-code-keyword:var(--purple);--dark-code-operator:var(--white);--dark-code-punctuation:var(--gray-300);--dark-code-comment:var(--gray-500);--md-bg-color:var(--gray-200);--dark-md-bg-color:var(--gray-800);--md-important-text-color:var(--dark-blue);--dark-md-important-text-color:var(--blue);--md-important-border-color:var(--dark-blue);--dark-md-important-border-color:var(--blue);--md-warning-text-color:var(--dark-red);--dark-md-warning-text-color:var(--red);--md-warning-border-color:var(--dark-red);--dark-md-warning-border-color:var(--red);--md-correct-text-color:var(--dark-green);--dark-md-correct-text-color:var(--green);--md-correct-border-color:var(--dark-green);--dark-md-correct-border-color:var(--green)}#root{grid-template-columns:1fr;grid-template-rows:75px 1fr auto;grid-template-areas:"header" "content-wrapper" "footer"}#main{grid-template-columns:100%;grid-template-areas:"article";overflow:hidden}#content-wrapper{grid-template-columns:auto;grid-template-areas:"main"}@media(min-width:1024px){#content-wrapper{grid-template-columns:300px 1fr;grid-template-areas:"sitenav main"}#main{grid-template-columns:70% 40%;grid-template-rows:auto;grid-template-areas:"article pagenav"}}article h1{font-size:var(--md-h1-size);font-weight:700}article ol{list-style-type:decimal;list-style-position:inside}article ol li,article ul li{line-height:1.75rem}article ul{list-style-type:disc;list-style-position:inside}article h2{font-size:var(--md-h2-size);padding-top:2rem;font-weight:500}article h3{font-size:var(--md-h3-size);padding-top:2rem;font-weight:500}article h4{font-size:var(--md-h4-size);padding-top:2rem;font-weight:500}article h5{font-size:var(--md-h5-size);padding-top:2rem;font-weight:500}article p{font-size:var(--md-p-size);line-height:1.75rem;font-weight:400}article p strong{font-weight:700}article pre{border-radius:var(--code-b-radius);overflow-x:auto;white-space:pre}article code{border-radius:var(--code-b-radius)}article a{color:var(--text-important);text-decoration:underline}html.dark article a{color:var(--dark-text-important)}article * code{background-color:var(--inline-code-bg-color);border-radius:var(--inline-code-b-radius);padding:.25rem}article p.custom-inline-code code{background-color:var(--inline-code-web-component-bg-color)}html.dark p.custom-inline-code code{background-color:var(--dark-inline-code-web-component-bg-color)}html.dark article * code{background-color:var(--dark-inline-code-bg-color)}article * code{padding:.25rem}article pre code{padding:0}.custom-scroll::-webkit-scrollbar{width:0}.sm-custom-scoll::-webkit-scrollbar{width:0}@media(min-width:992px){.custom-scroll::-webkit-scrollbar{width:12px}.sm-scroll::-webkit-scrollbar{width:4px}.custom-scroll::-webkit-scrollbar-track{background:#f1f1f1}.sm-scroll::-webkit-scrollbar-track{background:var(--white)}.custom-scroll::-webkit-scrollbar-thumb{background-color:var(--scroll-thumb-light);border-radius:10px}.custom-scroll::-webkit-scrollbar-thumb:hover{background-color:var(--gray);cursor:pointer}html.dark .custom-scroll::-webkit-scrollbar-thumb{background:var(--scroll-thumb-dark)}html.dark .custom-scroll::-webkit-scrollbar-thumb:hover{background-color:var(--gray);cursor:pointer}html.dark .custom-scroll::-webkit-scrollbar-track{background:var(--darkest-gray)}.custom-scroll::-webkit-scrollbar-thumb{background-color:var(--scroll-thumb-light);border-radius:10px}.custom-scroll::-webkit-scrollbar-thumb:hover{background-color:var(--gray);cursor:pointer}html.dark .custom-scroll::-webkit-scrollbar-thumb{background:var(--scroll-thumb-dark)}html.dark .custom-scroll::-webkit-scrollbar-thumb:hover{background-color:var(--gray);cursor:pointer}html.dark .custom-scroll::-webkit-scrollbar-track{background:var(--darkest-gray)}html.dark .sm-scroll::-webkit-scrollbar-track{background:var(--black)}}html.light code[class*=language-],html.light pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,andale mono,ubuntu mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}html.light pre[class*=language-]::-moz-selection,html.light pre[class*=language-] ::-moz-selection,html.light code[class*=language-]::-moz-selection,html.light code[class*=language-] ::-moz-selection{text-shadow:none}html.light pre[class*=language-]::selection,html.light pre[class*=language-] ::selection,html.light code[class*=language-]::selection,html.light code[class*=language-] ::selection{text-shadow:none}@media print{html.light code[class*=language-],html.light pre[class*=language-]{text-shadow:none}}html.light pre[class*=language-]{padding:1em;overflow:auto}html.light :not(pre)>code[class*=language-],html.light pre[class*=language-]{background:var(--code-bg-color)}html.light :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}html.light .token.prolog,html.light .token.doctype,html.light .token.cdata{color:var(--code-punctuation)}html.light .token.comment{color:var(--code-comment)}html.light .token.punctuation{color:var(--code-punctuation)}html.light .token.namespace{opacity:.7}html.light .token.property,html.light .token.tag,html.light .token.boolean,html.light .token.number,html.light .token.constant,html.light .token.symbol,html.light .token.deleted{color:var(--code-token-property)}html.light .token.attr-name,html.light .token.string,html.light .token.variable,html.light .token.char,html.light .token.inserted{color:var(--code-string)}html.light .token.selector{color:var(--code-token-selector)}html.light .token.operator,html.light .token.entity,html.light .token.url,html.light .language-css .token.string,html.light .style .token.string{color:var(--code-operator);background:var(--codeblock-light-background)}html.light .token.atrule,html.light .token.attr-value,html.light .token.builtin,html.light .token.class-name,html.light .token.keyword{color:var(--code-keyword)}html.light .token.function{color:var(--code-function)}html.light .token.regex,html.light .token.important{color:var(--code-important)}html.light .token.important,html.light .token.bold{font-weight:700}html.light .token.italic{font-style:italic}html.light .token.entity{cursor:help}html.dark code[class*=language-],html.dark pre[class*=language-]{color:#ccc;background:0 0;font-family:Consolas,Monaco,andale mono,ubuntu mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}html.dark pre[class*=language-]{padding:1em;overflow:auto}html.dark :not(pre)>code[class*=language-],html.dark pre[class*=language-]{background:var(--dark-code-bg-color)}html.dark :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}html.dark .token.prolog,html.dark .token.doctype,html.dark .token.cdata{color:var(--dark-code-punctuation)}html.dark .token.block-comment,html.dark .token.comment{color:var(--dark-code-comment)}html.dark .token.punctuation{color:var(--dark-code-punctuation)}html.dark .token.tag,html.dark .token.attr-name,html.dark .token.namespace,html.dark .token.deleted{color:#e2777a}html.dark .token.function-name{color:#6196cc}html.dark .token.boolean,html.dark .token.number,html.dark .token.function{color:var(--dark-code-function)}html.dark .token.property,html.dark .token.class-name,html.dark .token.constant,html.dark .token.symbol{color:var(--dark-code-token-property)}html.dark .token.selector,html.dark .token.important,html.dark .token.atrule{color:var(--dark-code-token-selector)}html.dark .token.keyword,html.dark .token.builtin{color:var(--dark-code-keyword)}html.dark .token.string,html.dark .token.char,html.dark .token.attr-value,html.dark .token.regex,html.dark .token.variable{color:var(--dark-code-string)}html.dark .token.operator,html.dark .token.entity,html.dark .token.url{color:var(--dark-code-operator)}html.dark .token.important,html.dark .token.bold{font-weight:700}html.dark .token.italic{font-style:italic}html.dark .token.entity{cursor:help}html.dark .token.inserted{color:green}div.code-toolbar{position:relative}div.code-toolbar>.toolbar{position:absolute;z-index:10;top:-.2em;right:.2em;transition:opacity .3s ease-in-out;opacity:1}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar:focus-within>.toolbar{opacity:1}div.code-toolbar>.toolbar>.toolbar-item{display:inline-block}div.code-toolbar>.toolbar>.toolbar-item>a{cursor:pointer}div.code-toolbar>.toolbar>.toolbar-item>button{background:0 0;border:0;color:inherit;font:inherit;line-height:normal;overflow:visible;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}div.code-toolbar>.toolbar>.toolbar-item>a,div.code-toolbar>.toolbar>.toolbar-item>button,div.code-toolbar>.toolbar>.toolbar-item>span{color:#bbb;font-size:.8em;padding:0 .5em;background:#f5f2f0;background:rgba(224,224,224,.2);box-shadow:0 2px rgba(0,0,0,.2);border-radius:.5em}div.code-toolbar>.toolbar>.toolbar-item>a:hover,div.code-toolbar>.toolbar>.toolbar-item>a:focus,div.code-toolbar>.toolbar>.toolbar-item>button:hover,div.code-toolbar>.toolbar>.toolbar-item>button:focus,div.code-toolbar>.toolbar>.toolbar-item>span:hover,div.code-toolbar>.toolbar>.toolbar-item>span:focus{color:inherit;text-decoration:none}*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::before,::after{--tw-content:''}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::before,::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media(min-width:480px){.container{max-width:480px}}@media(min-width:640px){.container{max-width:640px}}@media(min-width:768px){.container{max-width:768px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.container{max-width:1536px}}.\!visible{visibility:visible!important}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.top-0{top:0}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.my-12{margin-top:3rem;margin-bottom:3rem}.\!block{display:block!important}.block{display:block}.inline{display:inline}.\!flex{display:flex!important}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-6{height:1.5rem}.h-\[75px\]{height:75px}.h-full{height:100%}.h-screen{height:100vh}.w-6{width:1.5rem}.w-\[250px\]{width:250px}.w-\[80\%\]{width:80%}.w-full{width:100%}.w-screen{width:100vw}.shrink-0{flex-shrink:0}.rotate-90{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.break-words{overflow-wrap:break-word}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-l-4{border-left-width:4px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-\[var\(--b-color\)\]{border-color:var(--b-color)}.border-\[var\(--md-correct-border-color\)\]{border-color:var(--md-correct-border-color)}.border-\[var\(--md-important-border-color\)\]{border-color:var(--md-important-border-color)}.border-\[var\(--md-warning-border-color\)\]{border-color:var(--md-warning-border-color)}.bg-\[var\(--bg-hover-color\)\]{background-color:var(--bg-hover-color)}.bg-\[var\(--default-bg-color\)\]{background-color:var(--default-bg-color)}.bg-\[var\(--footer-bg-color\)\]{background-color:var(--footer-bg-color)}.bg-\[var\(--header-bg-color\)\]{background-color:var(--header-bg-color)}.bg-\[var\(--md-bg-color\)\]{background-color:var(--md-bg-color)}.bg-\[var\(--overlay-bg-color\)\]{background-color:var(--overlay-bg-color)}.bg-\[var\(--pagenav-bg-color\)\]{background-color:var(--pagenav-bg-color)}.bg-\[var\(--sitenav-bg-color\)\]{background-color:var(--sitenav-bg-color)}.p-2{padding:.5rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.pl-0{padding-left:0}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pl-5{padding-left:1.25rem}.pl-6{padding-left:1.5rem}.pl-7{padding-left:1.75rem}.pt-1{padding-top:.25rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.ordinal{--tw-ordinal:ordinal;font-variant-numeric:var(--tw-ordinal)var(--tw-slashed-zero)var(--tw-numeric-figure)var(--tw-numeric-spacing)var(--tw-numeric-fraction)}.text-\[var\(--default-text-color\)\]{color:var(--default-text-color)}.text-\[var\(--md-correct-text-color\)\]{color:var(--md-correct-text-color)}.text-\[var\(--md-important-text-color\)\]{color:var(--md-important-text-color)}.text-\[var\(--md-warning-text-color\)\]{color:var(--md-warning-text-color)}.text-\[var\(--text-important\)\]{color:var(--text-important)}.underline{text-decoration-line:underline}.no-underline{text-decoration-line:none}.opacity-70{opacity:.7}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.invert{--tw-invert:invert(100%);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.filter{filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.\[-\:\=\]{-:=}.hover\:border-\[var\(--b-hover-color\)\]:hover{border-color:var(--b-hover-color)}.hover\:bg-\[var\(--bg-hover-color\)\]:hover{background-color:var(--bg-hover-color)}@media(min-width:1024px){.lg\:invisible{visibility:hidden}.lg\:sticky{position:sticky}.lg\:top-\[75px\]{top:75px}.lg\:z-0{z-index:0}.lg\:block{display:block}.lg\:hidden{display:none}.lg\:w-auto{width:auto}.lg\:pl-8{padding-left:2rem}}@media(min-width:1280px){.xl\:pr-8{padding-right:2rem}}@media(min-width:1536px){.\32xl\:py-4{padding-top:1rem;padding-bottom:1rem}.\32xl\:pl-40{padding-left:10rem}}.dark\:block:where(.dark,.dark *){display:block}.dark\:hidden:where(.dark,.dark *){display:none}.dark\:border-\[var\(--dark-b-color\)\]:where(.dark,.dark *){border-color:var(--dark-b-color)}.dark\:border-\[var\(--dark-md-correct-border-color\)\]:where(.dark,.dark *){border-color:var(--dark-md-correct-border-color)}.dark\:border-\[var\(--dark-md-important-border-color\)\]:where(.dark,.dark *){border-color:var(--dark-md-important-border-color)}.dark\:border-\[var\(--dark-md-warning-border-color\)\]:where(.dark,.dark *){border-color:var(--dark-md-warning-border-color)}.dark\:bg-\[var\(--dark-bg-hover-color\)\]:where(.dark,.dark *){background-color:var(--dark-bg-hover-color)}.dark\:bg-\[var\(--dark-default-bg-color\)\]:where(.dark,.dark *){background-color:var(--dark-default-bg-color)}.dark\:bg-\[var\(--dark-footer-bg-color\)\]:where(.dark,.dark *){background-color:var(--dark-footer-bg-color)}.dark\:bg-\[var\(--dark-header-bg-color\)\]:where(.dark,.dark *){background-color:var(--dark-header-bg-color)}.dark\:bg-\[var\(--dark-md-bg-color\)\]:where(.dark,.dark *){background-color:var(--dark-md-bg-color)}.dark\:bg-\[var\(--dark-pagenav-bg-color\)\]:where(.dark,.dark *){background-color:var(--dark-pagenav-bg-color)}.dark\:bg-\[var\(--dark-sitenav-bg-color\)\]:where(.dark,.dark *){background-color:var(--dark-sitenav-bg-color)}.dark\:text-\[var\(--dark-default-text-color\)\]:where(.dark,.dark *){color:var(--dark-default-text-color)}.dark\:text-\[var\(--dark-md-correct-text-color\)\]:where(.dark,.dark *){color:var(--dark-md-correct-text-color)}.dark\:text-\[var\(--dark-md-important-text-color\)\]:where(.dark,.dark *){color:var(--dark-md-important-text-color)}.dark\:text-\[var\(--dark-md-warning-text-color\)\]:where(.dark,.dark *){color:var(--dark-md-warning-text-color)}.dark\:text-\[var\(--dark-text-important\)\]:where(.dark,.dark *){color:var(--dark-text-important)}.dark\:text-\[var\(--text-important\)\]:where(.dark,.dark *){color:var(--text-important)}.dark\:hover\:border-\[var\(--dark-b-hover-color\)\]:hover:where(.dark,.dark *){border-color:var(--dark-b-hover-color)}.hover\:dark\:bg-\[var\(--dark-bg-hover-color\)\]:where(.dark,.dark *):hover{background-color:var(--dark-bg-hover-color)}@media(min-width:1024px){.dark\:lg\:block:where(.dark,.dark *){display:block}.dark\:lg\:hidden:where(.dark,.dark *){display:none}} --------------------------------------------------------------------------------