├── .cutedoc.yml ├── .gitignore ├── LICENSE.txt ├── README.md ├── cmd └── cutedoc │ └── main.go ├── doc.go ├── docs ├── docs │ ├── index.html │ └── static │ │ ├── css │ │ └── main.css │ │ ├── img │ │ ├── icon.png │ │ └── logo.png │ │ └── js │ │ └── main.js ├── index.html ├── sources │ ├── about.md │ ├── building.md │ ├── installation.md │ └── manifest.md └── static │ ├── css │ └── main.css │ └── img │ ├── background.svg │ ├── icon.png │ └── logo.png ├── tasks.go └── template ├── bundle.go └── minimal ├── index.html.tmpl ├── main.css.tmpl └── main.js.tmpl /.cutedoc.yml: -------------------------------------------------------------------------------- 1 | build: 2 | dir: docs/docs 3 | meta: 4 | title: Cutedoc 5 | author: NickTheDev 6 | description: Cutedoc's documentation. 7 | branding: 8 | icon: docs/static/img/icon.png 9 | logo: docs/static/img/logo.png 10 | articles: 11 | Introduction: 12 | Intro: docs/sources/about.md 13 | Installing: docs/sources/installation.md 14 | Projects: 15 | Manifests: docs/sources/manifest.md 16 | Building: docs/sources/building.md -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Project files. 2 | .idea/* -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![cutedoc](https://github.com/NickTheDev/cutedoc/blob/master/docs/static/img/logo.png "Cutedoc") 2 | 3 | # cutedoc 4 | Cutedoc is a simple command line tool that allows you to generate beautiful static documentation using simple markdown files. 5 | You can learn more about the project at https://nickthedev.github.io/cutedoc. 6 | 7 | # Getting Started 8 | If you already have Go installed, you can easily grab the latest version of Cutedoc by using the go get command in the console. 9 | If your GOPATH/bin env variable is set, the cutedoc command will be accessible without having to specify the executable path. 10 | 11 | ``` 12 | $ go get github.com/NickTheDev/cutedoc/cmd/cutedoc 13 | ``` 14 | If you do not have or wish to install Go, you can grab a pre-built binary from Github. However, with this method you will have to 15 | optionally add the executable to your env variables yourself. 16 | 17 | # Demo 18 | Cutedoc's documentation was created with Cutedoc, and can be found at https://nickthedev.github.io/cutedoc/docs. 19 | 20 | -------------------------------------------------------------------------------- /cmd/cutedoc/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/nickthedev/cutedoc" 5 | "log" 6 | "os" 7 | ) 8 | 9 | // main loads the documentation config in either the current directory or a specified one and generates documentation using it. 10 | func main() { 11 | log.SetFlags(0) 12 | log.SetOutput(os.Stdout) 13 | 14 | if doc, err := cutedoc.New(); err == nil { 15 | if err = cutedoc.Run(doc); err != nil { 16 | log.Fatalf("An error occured generating documentation: \n\t%v.", err) 17 | } 18 | } else { 19 | log.Fatalf("An error occurred loading the documentation config: \n\t%v.", err) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | package cutedoc 2 | 3 | import ( 4 | "gopkg.in/yaml.v2" 5 | "io/ioutil" 6 | ) 7 | 8 | // config represents the default name of the cutedoc config file. 9 | const config = ".cutedoc.yml" 10 | 11 | // Doc represents the current model of the documentation being created. 12 | type Doc struct { 13 | Build Build 14 | Meta Meta 15 | Theme Theme 16 | Articles yaml.MapSlice 17 | } 18 | 19 | // Build represents options used during the build process. 20 | type Build struct { 21 | Dir string 22 | Minify bool 23 | } 24 | 25 | // Meta holds metadata of the documentation. 26 | type Meta struct { 27 | Title string 28 | Author string 29 | Description string 30 | Branding Branding 31 | } 32 | 33 | // Represents theme of the documentation. 34 | type Theme struct { 35 | Template string 36 | Colors Colors 37 | } 38 | 39 | // Represents color scheme of the documentation. 40 | type Colors struct { 41 | Primary string 42 | Secondary string 43 | Text string 44 | Nav string 45 | Background string 46 | } 47 | 48 | // Branding holds the paths to the branding of the documentation. 49 | type Branding struct { 50 | Logo string 51 | Icon string 52 | } 53 | 54 | // New reads the doc config in the current directory and creates a doc model based on it. 55 | func New() (*Doc, error) { 56 | bytes, err := ioutil.ReadFile(config) 57 | 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | doc := &Doc{Build{"docs", true}, 63 | Meta{"Docs", "", "Documentation page.", Branding{}}, 64 | Theme{"minimal", Colors{"3e4669", "c3c6de", "3e4669", "fff", "f6f7fb"}}, 65 | yaml.MapSlice{}} 66 | 67 | return doc, yaml.Unmarshal(bytes, doc) 68 | } 69 | -------------------------------------------------------------------------------- /docs/docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Cutedoc 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 46 | 68 |
69 |

Introduction

70 |
71 |
72 |

Intro

73 |
74 |

We've all been there, just finishing up our awesome project, whether it be a design framework 75 | or front-end library, and finding ourselves wondering how to create documentation for the project. 76 | We find ourselves envying the beautiful documentation of companies like Stripe, but instead opting 77 | out of creating custom documentation due to the amount of work it would require. Cutedoc is a simple 78 | command line tool that can be used to solve this problem.

79 | 80 |

Using technologies that you already know and love, like github flavored markdown, you can create beautiful documentation sites 81 | by simply creating markdown files and then stitching them together using a simple manifest file. Cutedoc leverages a high level 82 | of customization through the manifest file and allows you to specify the template theme and color scheme, the logo and icon of 83 | used, project metadata, and more.

84 | 85 |
86 |
87 |
88 | 89 |
90 |
91 |

Installing

92 |
93 |

If you already have Go installed, you can easily grab the latest version of 94 | Cutedoc by using the go get command in the console. If your GOPATH/bin env variable is set, the 95 | cutedoc command will be accessible without having to specify the executable path.

96 | 97 |
$ go get github.com/NickTheDev/cutedoc/cmd/cutedoc
 98 | 
99 | 100 |

If you do not have or wish to install Go, you can grab a pre-built binary from 101 | Github. However, with this method you will have 102 | to optionally add the executable to your env variables yourself.

103 | 104 |
105 |
106 |
107 | 108 |

Projects

109 |
110 |
111 |

Manifests

112 |
113 |

To create your project, start by creating a .cutedoc.yml file in a directory of your choice, usually 114 | the in the root of your project. This is the general structure of a manifest file:

115 | 116 |
meta:
117 |   title: Cutedoc
118 |   author: NickTheDev
119 |   description: Cutedoc's documentation.
120 |   branding:
121 |     icon: docs/static/img/icon.png
122 |     logo: docs/static/img/logo.png
123 | articles:
124 |   Introduction:
125 |     Intro: docs/sources/about.md
126 | 
127 |

128 | Meta

129 | 130 |

To describe basic characteristics of the project, you can define a meta section in the manifest 131 | file. In this section you may define meta such as the title, author, and description and the 132 | project branding.

133 | 134 |
# Project metadata.
135 | meta:
136 |   # Html header metadata title. Default is blank.
137 |   title: Cutedoc
138 | 
139 |   # Html header metadata author. Default is blank.
140 |   author: NickTheDev
141 | 
142 |   # Html header metadata description. Default is blank.
143 |   description: Cool documentation.
144 | 
145 |   # Project branding.
146 |   branding:
147 |     # Html header favicon, preferably 16 x 16. Default is null.
148 |     icon: path/to/icon.png
149 | 
150 |     # Logo of the project, preferably 200 x 100. Default is null.
151 |     logo: path/to/logo.png
152 | 
153 |

154 | Build

155 | 156 |

To configure the build of your project, you can define a build section in the manifest file. In this section you may 157 | specify the output directory of the build and whether to minify the production assets or not.

158 | 159 |
# Build config.
160 | build:
161 |   # Output directory of the documentation. Default is 'docs'.
162 |   dir: docs
163 | 
164 |   # Whether or not to minify the build assets (css, js). Default is true.
165 |   minify: true
166 | 
167 |

168 | Articles

169 | 170 |

To link markdown files in your project, you can define an articles section in the manifest file. 171 | In this section you may define article groups, and then place the links in them.

172 | 173 |
# Project articles.
174 | articles:
175 |   # Article group name.
176 |   Introduction:
177 |     # Path to article markdown file, may use github flavored markdown.
178 |     Intro: docs/sources/about.md
179 | 
180 |

181 | Theme

182 | 183 |

To configure the theme of your project, you can define a theme section in the manifest file. 184 | You may specify the template name, the only one currently being the minimal theme (The 185 | documentation you are reading right now uses the minimal theme). You can also 186 | define the color scheme of the template, namely the primary, secondary, text, nav, and 187 | background colors.

188 | 189 |
# Project theme.
190 | theme:
191 |   # Theme template, currently the only supported template is 'minimal'. Default is 'minimal'.
192 |   template: minimal
193 | 
194 |   # Template color scheme.
195 |   colors:
196 |     # Primary color used for headers and navigation group text colors. Default is 3e4669.
197 |     primary: 3e4669
198 | 
199 |     # Secondary color used an accent in the navigation and the body headers. Default is c3c6de.
200 |     secondary: c3c6de
201 | 
202 |     # Body text color used in the documentation. Default is 3e4669.
203 |     text: 3e4669
204 | 
205 |     # Navigation background color. Default is fff.
206 |     nav: fff
207 | 
208 |     # Background color. Default is f6f7fb.
209 |     background: f6f7fb
210 | 
211 | 212 |
213 |
214 |
215 | 216 |
217 |
218 |

Building

219 |
220 |

To build a project, simply execute the cutedoc command in a directory containing a .cutedoc.yml manifest file.

221 | 222 |
$ cutedoc
223 | 
224 | 225 |

Cutedoc will create documentation in the manifest's specified output directory the contents will look like this:

226 | 227 |
/static
228 |   /img
229 |     icon.png
230 |     logo.png
231 |   /css
232 |     main.css
233 |   /js
234 |     main.js
235 | index.html
236 | 
237 | 238 |
239 |
240 |
241 |
242 | 243 | -------------------------------------------------------------------------------- /docs/docs/static/css/main.css: -------------------------------------------------------------------------------- 1 | @import 'https://fonts.googleapis.com/css?family=Rubik';@import 'https://cdn.jsdelivr.net/npm/typeface-league-spartan@0.0.44/index.min.css';html,body{margin:0;padding:0;height:100%;font-size:100%;background-color:#f6f7fb;font-family:Rubik,sans-serif}.logo{margin:0 auto 45px;display:block;max-width:100px;max-height:50px}.sidebar{height:100%;width:280px;padding-top:2.5rem;position:fixed;display:block;top:0;left:0;background-color:#fff;overflow-y:auto;box-shadow:0 0 25px -4px rgba(0,0,0,.09)}.sidebar-content{margin-top:4rem}.nav-header{text-transform:uppercase;font:.6rem League Spartan,sans-serif;color:#3e4669;letter-spacing:.15em;transition:letter-spacing .2s}.nav-header:hover{letter-spacing:.2em}.nav-collapse{height:auto;padding:10px 0 3px}.nav-collapse li{padding:4px 0 4px 15px}.nav-collapse a{color:#c3c6de;font:.65rem League Spartan,sans-serif}.nav-collapse a:hover{opacity:.7}.dropdown-container{display:block;padding:9px 0 0 40px}#mobile-nav{z-index:3;position:fixed;top:0;left:0;width:100%}.nav-content{padding-top:15%;display:none}.nav-open .nav-content{display:block}.nav-open{background-color:#fff;height:100%}#nav-burger{top:15px;left:15px;position:fixed;width:20px;height:10px;z-index:3;cursor:pointer;-webkit-transition:.5s ease-in-out;transition:.5s ease-in-out}#nav-burger span{display:block;margin-bottom:3px;position:absolute;height:2px;width:100%;background:#3e4669;border-radius:20%;opacity:1;left:0;-webkit-transition:.25s ease-in-out;transition:.25s ease-in-out}#nav-burger span:nth-child(1){top:0}#nav-burger span:nth-child(2){top:6px}#nav-burger span:nth-child(3){top:12px}.nav-open #nav-burger span:nth-child(1){-webkit-transform:rotate(135deg);transform:rotate(135deg);top:6px}.nav-open #nav-burger span:nth-child(2){opacity:0;left:-30px}.nav-open #nav-burger span:nth-child(3){-webkit-transform:rotate(-135deg);transform:rotate(-135deg);top:6px}article{padding-top:2rem}.content pre{border-radius:.6rem;background-size:cover;padding:1em;margin:1.6rem 0!important;-webkit-box-shadow:0 0 38px 0 rgba(0,0,0,.2);box-shadow:0 0 38px 0 rgba(0,0,0,.2);font-size:1rem}.body{height:100%;padding:0 6% 6%;margin:2rem 0 0 280px;display:block}.article .content{font-size:.8rem;color:#3e4669;white-space:normal}.body-header{letter-spacing:.1rem;font:1.2rem League Spartan,sans-serif;color:#3e4669;margin-bottom:1rem;box-sizing:content-box}.article-header{letter-spacing:.1rem;font:1.6rem League Spartan,sans-serif;color:#3e4669;padding-top:5rem;box-sizing:content-box}.article-header:after{background:none repeat scroll 0 0 #c3c6de;top:.2rem;content:"";display:block;height:2px;position:relative;width:.8rem;border-radius:30%}@media screen and (max-width:768px){.body{padding:0 6% 6%;margin-left:0}}@keyframes bounce{50%{transform:translateY(-30%)}}@-webkit-keyframes bounce{50%{transform:translateY(-30%)}}::-webkit-scrollbar{width:8px;background-color:transparent;-webkit-border-radius:100px}::-webkit-scrollbar-thumb:vertical{background:#c3c6de;-webkit-border-radius:100px;background-clip:padding-box;border:2px solid transparent;min-height:10px} -------------------------------------------------------------------------------- /docs/docs/static/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickTheDev/cutedoc/038cc0ddacc598ae216127e094e6e5b4ee137f5d/docs/docs/static/img/icon.png -------------------------------------------------------------------------------- /docs/docs/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickTheDev/cutedoc/038cc0ddacc598ae216127e094e6e5b4ee137f5d/docs/docs/static/img/logo.png -------------------------------------------------------------------------------- /docs/docs/static/js/main.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll("div pre").forEach(function(value){hljs.highlightBlock(value);});document.getElementById("nav-burger").addEventListener("click",function(){document.getElementById("mobile-nav").classList.toggle("nav-open")});document.querySelectorAll(".nav-collapse li a").forEach(function(value){value.addEventListener("click",function(){document.getElementById("mobile-nav").classList.remove("nav-open");});});}); -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Cutedoc 8 | 9 | 10 | 11 | 12 | 13 | 22 |
23 |

Documentation made simple.

24 |

Easily generate stunning static documentation for any project using simple markdown.

25 | go to docs 26 |
27 | 28 | -------------------------------------------------------------------------------- /docs/sources/about.md: -------------------------------------------------------------------------------- 1 | We've all been there, just finishing up our awesome project, whether it be a design framework 2 | or front-end library, and finding ourselves wondering how to create documentation for the project. 3 | We find ourselves envying the beautiful documentation of companies like Stripe, but instead opting 4 | out of creating custom documentation due to the amount of work it would require. Cutedoc is a simple 5 | command line tool that can be used to solve this problem. 6 | 7 | Using technologies that you already know and love, like github flavored markdown, you can create beautiful documentation sites 8 | by simply creating markdown files and then stitching them together using a simple manifest file. Cutedoc leverages a high level 9 | of *customization* through the manifest file and allows you to specify the template theme and color scheme, the logo and icon of 10 | used, project metadata, and more. -------------------------------------------------------------------------------- /docs/sources/building.md: -------------------------------------------------------------------------------- 1 | To build a project, simply execute the *cutedoc* command in a directory containing a *.cutedoc.yml* manifest file. 2 | ``` 3 | $ cutedoc 4 | ``` 5 | Cutedoc will create documentation in the manifest's specified output directory the contents will look like this: 6 | ``` 7 | /static 8 | /img 9 | icon.png 10 | logo.png 11 | /css 12 | main.css 13 | /js 14 | main.js 15 | index.html 16 | ``` 17 | -------------------------------------------------------------------------------- /docs/sources/installation.md: -------------------------------------------------------------------------------- 1 | If you already have [Go](https://golang.org/) installed, you can easily grab the latest version of 2 | Cutedoc by using the *go get* command in the console. If your GOPATH/bin env variable is set, the 3 | cutedoc command will be accessible without having to specify the executable path. 4 | 5 | ``` 6 | $ go get github.com/NickTheDev/cutedoc/cmd/cutedoc 7 | ``` 8 | If you do not have or wish to install Go, you can grab a pre-built binary from 9 | [Github](https://github.com/NickTheDev/cutedoc/releases). However, with this method you will have 10 | to optionally add the executable to your env variables yourself. -------------------------------------------------------------------------------- /docs/sources/manifest.md: -------------------------------------------------------------------------------- 1 | To create your project, start by creating a *.cutedoc.yml* file in a directory of your choice, usually 2 | the in the root of your project. This is the general structure of a manifest file: 3 | ``` 4 | meta: 5 | title: Cutedoc 6 | author: NickTheDev 7 | description: Cutedoc's documentation. 8 | branding: 9 | icon: docs/static/img/icon.png 10 | logo: docs/static/img/logo.png 11 | articles: 12 | Introduction: 13 | Intro: docs/sources/about.md 14 | ``` 15 | ### Meta 16 | 17 | To describe basic characteristics of the project, you can define a meta section in the manifest 18 | file. In this section you may define meta such as the title, author, and description and the 19 | project branding. 20 | ``` 21 | # Project metadata. 22 | meta: 23 | # Html header metadata title. Default is blank. 24 | title: Cutedoc 25 | 26 | # Html header metadata author. Default is blank. 27 | author: NickTheDev 28 | 29 | # Html header metadata description. Default is blank. 30 | description: Cool documentation. 31 | 32 | # Project branding. 33 | branding: 34 | # Html header favicon, preferably 16 x 16. Default is null. 35 | icon: path/to/icon.png 36 | 37 | # Logo of the project, preferably 200 x 100. Default is null. 38 | logo: path/to/logo.png 39 | ``` 40 | ### Build 41 | 42 | To configure the build of your project, you can define a build section in the manifest file. In this section you may 43 | specify the output directory of the build and whether to minify the production assets or not. 44 | ``` 45 | # Build config. 46 | build: 47 | # Output directory of the documentation. Default is 'docs'. 48 | dir: docs 49 | 50 | # Whether or not to minify the build assets (css, js). Default is true. 51 | minify: true 52 | ``` 53 | ### Articles 54 | 55 | To link markdown files in your project, you can define an articles section in the manifest file. 56 | In this section you may define article groups, and then place the links in them. 57 | ``` 58 | # Project articles. 59 | articles: 60 | # Article group name. 61 | Introduction: 62 | # Path to article markdown file, may use github flavored markdown. 63 | Intro: docs/sources/about.md 64 | ``` 65 | ### Theme 66 | To configure the theme of your project, you can define a theme section in the manifest file. 67 | You may specify the template name, the only one currently being the minimal theme (The 68 | documentation you are reading right now uses the minimal theme). You can also 69 | define the color scheme of the template, namely the primary, secondary, text, nav, and 70 | background colors. 71 | ``` 72 | # Project theme. 73 | theme: 74 | # Theme template, currently the only supported template is 'minimal'. Default is 'minimal'. 75 | template: minimal 76 | 77 | # Template color scheme. 78 | colors: 79 | # Primary color used for headers and navigation group text colors. Default is 3e4669. 80 | primary: 3e4669 81 | 82 | # Secondary color used an accent in the navigation and the body headers. Default is c3c6de. 83 | secondary: c3c6de 84 | 85 | # Body text color used in the documentation. Default is 3e4669. 86 | text: 3e4669 87 | 88 | # Navigation background color. Default is fff. 89 | nav: fff 90 | 91 | # Background color. Default is f6f7fb. 92 | background: f6f7fb 93 | ``` -------------------------------------------------------------------------------- /docs/static/css/main.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Rubik'); 2 | @import url('https://cdn.jsdelivr.net/npm/typeface-league-spartan@0.0.44/index.min.css'); 3 | 4 | html, body { 5 | height: 100%; 6 | } 7 | 8 | html { 9 | margin: 0; 10 | padding: 0; 11 | background: url('../img/background.svg') no-repeat; 12 | background-size: cover; 13 | overflow: hidden; 14 | font-family: Rubik, -apple-system, BlinkMacSystemFont, Roboto, Segoe UI, Helvetica, Arial, sans-serif; 15 | } 16 | 17 | .nav { 18 | display: block; 19 | position: fixed; 20 | top: 0; 21 | left: 0; 22 | height: 170px; 23 | width: 100%; 24 | } 25 | 26 | .logo { 27 | width: 100px; 28 | height: 50px; 29 | margin-left: 7rem; 30 | } 31 | 32 | .docs { 33 | font-weight: 500; 34 | font-size: .8rem; 35 | color: #C3C6DF; 36 | } 37 | 38 | 39 | .github { 40 | display: block; 41 | margin: 0 8rem 0 1.5em; 42 | padding: .3em 1.5em; 43 | font-size: .8rem; 44 | transition: transform .3s; 45 | border: 2px solid #FF00B6; 46 | background-color: #fff; 47 | color: #FF00B6; 48 | border-radius: 20px; 49 | font-weight: bold; 50 | } 51 | 52 | .github:hover { 53 | transform: scale(1.05); 54 | } 55 | 56 | .github:focus { 57 | outline: none; 58 | } 59 | 60 | .headers { 61 | margin: 11rem 0 0 6.8rem; 62 | width: 11.5em; 63 | font: 1.8rem League Spartan; 64 | color: #192337; 65 | } 66 | 67 | .description { 68 | font: .9rem Rubik; 69 | color: #ACB0CC; 70 | margin-top: 1.5em; 71 | } 72 | 73 | .doc-link { 74 | font: .8rem League Spartan; 75 | color: #FF00B6; 76 | margin-top: 1.3em; 77 | } 78 | 79 | .link-arrow { 80 | font: .8rem sans-serif; 81 | font-weight: bold; 82 | color: #FF00B6; 83 | } 84 | 85 | .is-left-center { 86 | display: flex; 87 | justify-content: flex-start; 88 | align-items: center; 89 | } 90 | 91 | .is-right-center { 92 | display: flex; 93 | justify-content: flex-end; 94 | align-items: center; 95 | } 96 | 97 | @media screen and (max-width: 768px) { 98 | html { 99 | background: #fff; 100 | } 101 | 102 | .logo { 103 | margin-left: 2em 104 | } 105 | 106 | .github { 107 | margin-right: 2em 108 | } 109 | 110 | .headers { 111 | margin: 15rem auto 0 auto; 112 | } 113 | } -------------------------------------------------------------------------------- /docs/static/img/background.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/static/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickTheDev/cutedoc/038cc0ddacc598ae216127e094e6e5b4ee137f5d/docs/static/img/icon.png -------------------------------------------------------------------------------- /docs/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickTheDev/cutedoc/038cc0ddacc598ae216127e094e6e5b4ee137f5d/docs/static/img/logo.png -------------------------------------------------------------------------------- /tasks.go: -------------------------------------------------------------------------------- 1 | package cutedoc 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "github.com/nickthedev/cutedoc/template" 7 | "github.com/shurcooL/github_flavored_markdown" 8 | "github.com/tdewolff/minify" 9 | "github.com/tdewolff/minify/css" 10 | "github.com/tdewolff/minify/js" 11 | "io/ioutil" 12 | "log" 13 | "os" 14 | "strings" 15 | tmpl "text/template" 16 | ) 17 | 18 | var ( 19 | // tasks represents all the steps of the generation process. 20 | tasks = []task{ 21 | initBuild, 22 | copyBranding, 23 | copyScript, 24 | copyStatic, 25 | copyTemplate, 26 | } 27 | 28 | // templates represent the supported themes. 29 | templates = map[string]string{ 30 | "minimal": "template/minimal", 31 | } 32 | 33 | // packer compresses assets for production. 34 | minifier = minify.New() 35 | ) 36 | 37 | // tasks represents a step of the generation process. 38 | type task func(doc *Doc) error 39 | 40 | // copyImage copies the image to the output minimal directory if it is not null. 41 | func copyImage(doc *Doc, image, output string) error { 42 | if image != "" { 43 | icon, err := ioutil.ReadFile(image) 44 | 45 | if err != nil { 46 | return err 47 | } 48 | 49 | if err := os.MkdirAll(doc.Build.Dir+"/static/img", os.ModePerm); err != nil { 50 | return err 51 | } 52 | 53 | ioutil.WriteFile(doc.Build.Dir+"/static/img/"+output, icon, os.ModePerm) 54 | } 55 | 56 | return nil 57 | } 58 | 59 | // initBuild checks the template and creates the output directory. 60 | func initBuild(doc *Doc) error { 61 | if _, ok := templates[doc.Theme.Template]; !ok { 62 | return errors.New("unsupported template theme") 63 | } 64 | 65 | if err := os.RemoveAll(doc.Build.Dir); err != nil { 66 | return err 67 | } 68 | 69 | return os.MkdirAll(doc.Build.Dir, os.ModePerm) 70 | } 71 | 72 | // copyBranding copies the logo and icon if they are not null to the minimal output directory. 73 | func copyBranding(doc *Doc) error { 74 | if err := copyImage(doc, doc.Meta.Branding.Icon, "icon.png"); err != nil { 75 | return err 76 | } 77 | 78 | if err := copyImage(doc, doc.Meta.Branding.Logo, "logo.png"); err != nil { 79 | return err 80 | } 81 | 82 | return nil 83 | } 84 | 85 | // copyScript copies the template script output minimal directory. 86 | func copyScript(doc *Doc) error { 87 | if err := os.MkdirAll(doc.Build.Dir+"/static/js", os.ModePerm); err != nil { 88 | return err 89 | } 90 | 91 | asset, err := template.Asset(templates[doc.Theme.Template] + "/main.js.tmpl") 92 | 93 | if err != nil { 94 | return err 95 | } 96 | 97 | if doc.Build.Minify { 98 | packed, err := minifier.Bytes("text/javascript", asset) 99 | 100 | if err != nil { 101 | return err 102 | } else { 103 | asset = packed 104 | } 105 | } 106 | 107 | return ioutil.WriteFile(doc.Build.Dir+"/static/js/main.js", asset, os.ModePerm) 108 | } 109 | 110 | // copyStatic transfers the template stylesheet to the output minimal directory. 111 | func copyStatic(doc *Doc) error { 112 | if err := os.MkdirAll(doc.Build.Dir+"/static/css", os.ModePerm); err != nil { 113 | return err 114 | } 115 | 116 | asset, err := template.Asset(templates[doc.Theme.Template] + "/main.css.tmpl") 117 | 118 | if err != nil { 119 | return err 120 | } 121 | 122 | format, err := tmpl.New("style").Parse(string(asset)) 123 | 124 | if err != nil { 125 | return err 126 | } 127 | 128 | var buffer bytes.Buffer 129 | 130 | if err := format.Execute(&buffer, doc.Theme.Colors); err != nil { 131 | return err 132 | } 133 | 134 | var data = buffer.Bytes() 135 | 136 | if doc.Build.Minify { 137 | data, err = minifier.Bytes("text/css", data) 138 | 139 | if err != nil { 140 | return err 141 | } 142 | } 143 | 144 | return ioutil.WriteFile(doc.Build.Dir+"/static/css/main.css", data, os.ModePerm) 145 | } 146 | 147 | // copyTemplate injects the doc model into the template page and copies it to the output directory. 148 | func copyTemplate(doc *Doc) error { 149 | asset, err := template.Asset(templates[doc.Theme.Template] + "/index.html.tmpl") 150 | 151 | if err != nil { 152 | return err 153 | } 154 | 155 | format, err := tmpl.New("doc").Funcs(tmpl.FuncMap{ 156 | "readContent": func(path string) string { 157 | content, err := ioutil.ReadFile(path) 158 | 159 | if err != nil { 160 | log.Fatalf("An error occured generating documentation: \n\t%v.", err) 161 | } 162 | 163 | return string(github_flavored_markdown.Markdown(content)) 164 | }, 165 | "idFrom": func(name string) string { 166 | return strings.Replace(strings.ToLower(name), " ", "-", -1) 167 | }, 168 | }).Parse(string(asset)) 169 | 170 | if err != nil { 171 | return err 172 | } 173 | 174 | dst, err := os.Create(doc.Build.Dir + "/index.html") 175 | 176 | if err != nil { 177 | return err 178 | } 179 | 180 | defer dst.Close() 181 | 182 | return format.Execute(dst, doc) 183 | } 184 | 185 | // Run executes the documentation generation tasks. 186 | func Run(doc *Doc) error { 187 | if doc.Build.Minify { 188 | minifier.AddFunc("text/css", css.Minify) 189 | minifier.AddFunc("text/javascript", js.Minify) 190 | } 191 | 192 | for _, task := range tasks { 193 | if err := task(doc); err != nil { 194 | return err 195 | } 196 | 197 | } 198 | 199 | return nil 200 | } 201 | -------------------------------------------------------------------------------- /template/bundle.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. DO NOT EDIT. 2 | // memcopy: true 3 | // compress: true 4 | // decompress: once 5 | // metadata: true 6 | // asset-dir: true 7 | // restore: true 8 | // sources: 9 | // template/minimal/index.html.tmpl 10 | // template/minimal/main.css.tmpl 11 | // template/minimal/main.js.tmpl 12 | 13 | package template 14 | 15 | import ( 16 | "bytes" 17 | "compress/flate" 18 | "io" 19 | "os" 20 | "path/filepath" 21 | "strings" 22 | "sync" 23 | "time" 24 | 25 | "github.com/tmthrgd/go-bindata/restore" 26 | ) 27 | 28 | type asset struct { 29 | name string 30 | data string 31 | size int64 32 | mode os.FileMode 33 | time time.Time 34 | 35 | once sync.Once 36 | bytes []byte 37 | err error 38 | } 39 | 40 | func (a *asset) Name() string { 41 | return a.name 42 | } 43 | 44 | func (a *asset) Size() int64 { 45 | return a.size 46 | } 47 | 48 | func (a *asset) Mode() os.FileMode { 49 | return a.mode 50 | } 51 | 52 | func (a *asset) ModTime() time.Time { 53 | return a.time 54 | } 55 | 56 | func (*asset) IsDir() bool { 57 | return false 58 | } 59 | 60 | func (*asset) Sys() interface{} { 61 | return nil 62 | } 63 | 64 | // _bindata is a table, holding each asset generator, mapped to its name. 65 | var _bindata = map[string]*asset{ 66 | "template/minimal/index.html.tmpl": &asset{ 67 | name: "index.html.tmpl", 68 | data: "" + 69 | "\xec\x56\xcd\x8e\xdb\x36\x10\xbe\x17\xe8\x3b\xb0\x6c\x8e\x91\xb8\xce\xa1\x68\x03\xca\xc0\x76\x93" + 70 | "\x00\x41\x5b\xb4\x87\x4d\xd1\x1e\xc7\xe4\x58\x1a\x2f\x45\xaa\x24\xe5\x5d\x43\xf0\xbb\x17\xb4\x69" + 71 | "\x5b\xb2\x1d\x34\x45\xf6\xd0\x02\x39\x89\xe4\xfc\x7c\xf3\xf7\x91\x92\xdf\xbc\xf9\xf5\xee\xfe\xcf" + 72 | "\xdf\xde\xb2\x26\xb6\x66\xfe\xf5\x57\x32\x7f\x19\x93\x0d\x82\xde\xad\x18\x93\x2d\x46\x60\xaa\x01" + 73 | "\x1f\x30\x56\xfc\xc3\xfd\xbb\xe2\x7b\x3e\x91\x35\x31\x76\x05\xfe\xd5\xd3\xba\xe2\x7f\x14\x1f\x6e" + 74 | "\x8b\x3b\xd7\x76\x10\x69\x61\x90\x33\xe5\x6c\x44\x1b\x2b\x4e\x58\xa1\xae\x71\x6a\x6a\xa1\xc5\x8a" + 75 | "\xaf\x09\x1f\x3b\xe7\xe3\x48\xfb\x91\x74\x6c\x2a\x8d\x6b\x52\x58\xec\x36\x2f\x19\x59\x8a\x04\xa6" + 76 | "\x08\x0a\x0c\x56\xb3\xf2\xe6\x9a\x2f\xe8\x63\xe3\xfc\xc8\xd3\x30\x94\xbf\x60\x84\xf2\x76\x27\xd8" + 77 | "\x6e\xaf\x19\x69\x0c\xca\x53\x17\xc9\xd9\x2b\x96\x6f\x4e\xd2\x91\x79\xa4\x68\x70\x7e\xd0\xb9\x4f" + 78 | "\xbb\xed\x56\x8a\xc3\x31\x2d\x99\x45\xb6\x17\xfe\xe8\xc1\x6a\xb2\x75\xf9\x5e\x39\xcb\x38\xdf\x6e" + 79 | "\xb3\x0f\x43\xf6\x81\x79\x34\x15\x27\x95\xa0\xe3\xa6\xc3\x8a\x53\x0b\x35\x8a\xce\xd6\x9c\x35\x1e" + 80 | "\x97\x15\x0f\x11\x22\x29\x41\x6d\x2d\x92\x5e\x99\x44\xf3\x61\x40\xab\xaf\x78\x0a\x71\x63\x30\x34" + 81 | "\x88\xf1\x60\x9e\xfa\x13\x5e\x0b\xa1\xb4\x5d\x85\x52\x19\xd7\xeb\xa5\x01\x8f\xa5\x72\xad\x80\x15" + 82 | "\x3c\x09\x43\x8b\x20\x1a\xaa\x1b\x43\x75\x13\xcb\x55\x10\x3f\x94\xb3\x57\xe5\x8d\xd8\x3b\x13\x10" + 83 | "\x5d\x5b\x38\x8b\x85\x06\xff\x50\xb6\x64\x4b\x15\xc2\xb1\x12\xcf\x80\xbd\xe8\x4d\x0b\xe2\xa6\xfc" + 84 | "\xae\x7c\x25\x54\xc8\xfb\x7f\x05\x94\x6b\x94\x8c\x5b\x38\xb3\xdb\xb7\x8f\x05\xaf\x3e\xab\x18\xa7" + 85 | "\xb3\x14\xd8\x2a\xf0\xb9\x14\x7b\xd7\xcf\x0c\x64\xc0\xd6\x3d\xd4\x18\xc4\x06\x5a\xf3\x49\x68\x39" + 86 | "\xfd\x55\xce\xfe\x42\x5d\x8a\x23\xa5\xe5\xc2\xe9\x4d\xf6\xc1\x98\xb4\xb0\x66\xa4\x2b\xde\xba\x05" + 87 | "\x19\x2c\x2c\xac\x39\x53\x06\x42\xa8\x38\x85\xa2\x21\xad\xd1\x16\x11\x16\x06\x23\x3f\x5a\x31\x26" + 88 | "\x35\xed\xed\x2c\xac\x8b\x45\xef\x6b\xf4\x63\x71\x0a\xaf\x03\x9b\x82\x48\x9f\xcf\x11\x48\xa1\x69" + 89 | "\x7d\x8e\x9c\x23\x4c\xe0\x99\xaf\x67\xe8\x23\xa5\xa4\x00\x64\xd1\x33\x0a\xc5\xd2\xf4\xa4\xa7\xba" + 90 | "\x8c\x49\x6a\xeb\x83\xb6\x71\xb5\xe3\x0c\x4c\xac\xf8\xcf\xbb\xe5\xb8\xbe\x89\x82\x49\x61\x4f\xc1" + 91 | "\x09\xe0\x59\x94\x8c\x0d\x83\x07\x5b\x23\x7b\x41\x56\xe3\xd3\x4b\xf6\x02\x0d\xb6\x68\x23\x7b\x5d" + 92 | "\xb1\xf2\xd6\x47\x52\x06\xc3\x81\xc0\x97\x51\x6b\xef\x3a\xed\x1e\x6d\x71\x0c\xff\x22\xea\x6e\x5c" + 93 | "\x86\xd4\x5f\xf4\x9c\x2d\x9d\xaf\xb8\x6a\x50\x3d\x2c\xdc\x53\x31\x0c\xa4\xdf\x79\xd7\x1e\xd1\xcb" + 94 | "\x9f\x70\x93\x6e\xb1\x61\x98\x9e\x48\xd1\x9d\xbb\xef\xcd\xb4\xcc\xc6\x40\x17\x30\x99\xe6\xc4\x02" + 95 | "\xaa\x74\x29\xbe\xcf\xf9\xe5\xed\xdb\x53\x9a\x47\x88\xdf\xc1\xf4\x38\xcd\x35\x33\x7a\x2e\x21\x33" + 96 | "\xf8\xdb\x53\xac\x53\x4f\xa3\x90\xaf\x09\xa4\x80\xb9\x14\x86\xa6\x37\xe2\xa9\x2f\xbd\xb9\xd2\xa8" + 97 | "\x0b\xdd\x69\xff\xa4\xb0\x30\xda\x41\x20\x8d\x87\x62\xa4\xf5\x02\x76\xc3\x94\xd9\xb1\xa7\x0e\xff" + 98 | "\xc8\x8c\x66\xfd\xff\xe8\x9c\x7e\x99\xd2\xff\xf3\x94\xee\x06\xf3\xb4\xcf\xc0\x87\x82\xa4\x8b\x9e" + 99 | "\xe5\xb3\x51\x41\x3e\xad\xd3\xb2\x99\x1d\xfc\xc0\x5e\x78\x68\xde\x95\xae\x34\xb3\x67\xa9\xb7\xcc" + 100 | "\x48\xbb\x87\xe5\x9f\x0a\xfd\xb1\x91\xcc\x3e\x2e\xe6\xf0\x94\x4f\xaa\xcb\x38\x99\xeb\xfd\x6a\x66" + 101 | "\xe7\x1e\xce\xb8\x7a\x41\xe6\xcc\x27\x04\x7d\xb7\x17\x5f\x84\x7e\x75\xc2\x2e\x9f\x8e\x8b\x27\x4f" + 102 | "\xe4\xa4\x8e\x67\x79\x32\xf2\x47\x8a\x8c\x93\xdf\xfa\xfc\xc2\x4b\xb1\xfb\xa3\xff\x3b\x00\x00\xff" + 103 | "\xff", 104 | size: 3049, 105 | mode: 0666, 106 | time: time.Unix(1529704804, 441809400), 107 | }, 108 | "template/minimal/main.css.tmpl": &asset{ 109 | name: "main.css.tmpl", 110 | data: "" + 111 | "\xac\x57\xdf\x6f\xdb\x36\x10\x7e\x0f\x90\xff\x81\x6b\x11\x34\x06\x4a\x59\x92\xed\x34\x55\x30\xac" + 112 | "\xd8\xf3\x30\x0c\xeb\x5e\xf6\x48\x49\x67\x8b\x0b\x45\x12\x24\xe5\x1f\x0d\xf2\xbf\x0f\x22\xf5\x83" + 113 | "\xa2\xe5\x24\x5d\x07\x18\x81\xc4\xf0\x8e\xf7\x7d\xbc\xfb\xee\xf4\x85\xd6\x52\x28\x83\x1a\xc5\x6e" + 114 | "\x3f\x54\xc6\x48\x9d\x2d\x97\x5b\xc1\x8d\x8e\x76\x42\xec\x18\x10\x49\x75\x54\x88\x7a\x59\x68\xfd" + 115 | "\xcb\x96\xd4\x94\x9d\x7e\xfe\xb3\xc9\xe9\xe3\x87\xc5\xc3\xf5\xd5\xac\x79\x51\xf2\xe8\x1f\x5d\x02" + 116 | "\xa3\x7b\x15\x71\x30\x4b\x2e\xeb\xa5\x39\x49\xd8\x92\x02\x30\x03\xb2\x6b\x00\x6b\x49\x94\x21\xfc" + 117 | "\x4b\x1c\xc5\xd1\x7a\xbd\xa4\xbc\x84\x63\x54\x53\x1e\x15\x5a\x5b\xd7\xd7\x57\x95\xa9\xd9\x47\x94" + 118 | "\x8b\xf2\x84\x9e\xae\xaf\x10\xaa\x89\xda\x51\x9e\xa1\xf8\xa1\x7d\x93\xa4\x2c\x29\xdf\xf5\xaf\x15" + 119 | "\xd0\x5d\x65\x32\x94\xc4\xf1\x8d\x5d\x68\x41\x60\x4d\xbf\x81\xb7\x96\x93\xe2\x71\xa7\x44\xc3\x4b" + 120 | "\x5c\x08\x26\x54\x86\xde\x3f\x3d\x45\xbf\x0e\xab\xcf\xcf\xa3\xa9\xc3\x9a\x21\x0b\xf6\x23\xd2\x84" + 121 | "\x6b\xac\x41\xd1\xed\xc3\xf5\xd5\x73\x1b\x5e\xc4\xc4\x4e\x04\x91\x21\xd2\x18\x81\xd6\x1b\x79\xb4" + 122 | "\x4f\xd6\x5b\x49\xb5\x64\xe4\x94\xa1\x9c\x89\xe2\xf1\xc1\xed\x3f\xe2\x03\x2d\x4d\x65\x63\x93\xc7" + 123 | "\x61\xb1\x47\xb1\x71\x8b\xee\x1c\x4d\x4b\xc8\x89\x72\x47\x9d\xe1\xec\xfc\xa4\xf7\xbd\x9f\x8e\x18" + 124 | "\x6c\x84\xcc\x50\x1a\x6d\x14\xd4\x6e\x5d\x68\x6a\xa8\xe0\x19\xda\xd2\x23\x94\x97\x62\xb3\x66\x8e" + 125 | "\x53\x06\x5b\xd3\x3f\xcf\x53\xf7\x3b\xd9\x77\x9c\x89\x3d\xa8\x2d\x13\x07\x7c\xca\x46\xe8\xb9\x38" + 126 | "\x62\x5d\x91\x52\x1c\x5a\x6e\x62\x94\xb6\xc4\xe0\xb5\x3c\x22\xb5\xcb\xc9\x6d\xfc\x11\x75\xbf\x28" + 127 | "\xfe\xbc\x08\xf1\xe2\x42\x70\x03\xdc\xf8\x14\x3b\x50\x6b\x07\xc9\xed\xe6\x64\x8f\x2b\x20\x25\x74" + 128 | "\x04\x19\x38\x1a\x6c\x14\xe1\x7a\x2b\x54\x9d\xa1\x46\x4a\x50\x05\xd1\x30\x5c\x6d\x86\xa2\x3b\x05" + 129 | "\x35\xfa\xcd\x66\x22\xfa\xea\x32\x31\xb8\x62\x84\x3c\x98\x7f\x28\x5a\x13\x75\xea\xa0\x32\x30\x06" + 130 | "\x54\x9b\xc1\x85\x4d\xc0\x28\xd9\x74\x14\xdb\x63\x3b\x92\xa7\xbb\x50\x94\xea\x99\x90\xb3\xaa\xe5" + 131 | "\xcd\x05\x7e\xe6\x36\x0d\x50\x16\x82\x31\x22\x35\x4c\x13\x61\x20\x7b\x28\x88\x24\x96\x47\x14\xa3" + 132 | "\x95\x97\x42\x13\x73\x46\x9d\x87\xc1\x60\x6d\xf7\xb7\x7f\x93\xcd\x25\x23\xe2\x6c\x3c\x52\xbe\x42" + 133 | "\x21\x78\x39\xd2\xd2\x53\xbb\x79\x95\xdb\x39\xf7\x3e\x13\xa2\xa5\xc0\x9c\x32\x14\x47\x9f\x86\xed" + 134 | "\xa5\x12\xb2\x14\x07\x6e\xd3\x82\x50\xde\x6f\x9e\x49\xe1\x01\xd8\x67\x0b\x2c\x46\x6b\xaf\x9c\xde" + 135 | "\xd7\x22\xa7\x0c\x30\x27\x7b\xe7\xe0\x1b\xb6\xe2\x93\xa1\xd5\xc5\x32\xb9\x50\x13\x63\x09\xdf\x04" + 136 | "\xa8\xbc\xc4\x9d\x94\x63\xb2\xb9\x99\xd6\x1d\x17\x1c\x26\xb6\x42\x02\x47\xe7\x5e\xce\x50\x06\x16" + 137 | "\x4f\x6f\xa9\xd1\x40\x3b\x1c\x1d\xad\x8b\xbc\x51\xbb\xa1\x7e\x5c\x9c\x9d\x98\x38\xb8\xc3\xeb\x1c" + 138 | "\x39\xbd\x00\xf5\xfa\x33\x9e\xd2\x2d\x04\x04\x17\x8d\xd2\x6d\x6c\x52\x50\x6e\x40\xd9\x35\x7c\x80" + 139 | "\xfc\x91\x76\x75\xdb\x9d\x10\x47\x1b\x8d\x80\x68\xc0\x94\x63\xd1\x98\xb3\x0a\x9b\xd9\x70\x06\x49" + 140 | "\x4b\xc2\x2f\xe6\x49\xa7\x29\xb9\x30\x46\xd4\x59\x57\x30\x3e\x48\x92\x6b\xc1\x1a\x03\x13\x5c\x69" + 141 | "\xb7\x6d\x7a\xfb\x3e\xfb\x73\xa2\x91\x0b\x55\x82\xc2\x8a\x94\xb4\xd1\x2d\x5b\xce\x68\x48\xf5\xe4" + 142 | "\x2c\xbb\xe6\x39\x49\x5f\x25\x25\x7d\x1b\x2b\x19\x37\x15\x2e\x2a\xca\xca\xdb\x64\xe1\x5d\x7d\xfc" + 143 | "\x06\x83\xd4\x37\xb8\xf3\x6a\xeb\xb2\xc9\xca\x37\x49\xd2\x40\x66\x6c\x0e\xbf\x21\xc2\x09\x27\x4e" + 144 | "\xdf\x95\x30\xc4\xc0\x6d\xb2\xda\x94\xb0\x5b\x8c\x7c\x5c\xfe\x6f\x10\xf4\x9b\x02\xe8\x11\x8f\xd2" + 145 | "\xe4\xdd\x17\x5e\xc5\xdf\xe9\x6e\xf5\x2a\x1e\xfc\x32\x20\xfc\x12\x22\xa2\x0c\x2d\x18\xcc\xe8\x4f" + 146 | "\xea\x77\xce\x5e\x60\xa4\xea\xb6\x06\x39\x1a\xdb\x36\x19\x76\x7f\x37\x52\x15\xad\x5a\x07\x6d\xa7" + 147 | "\xdb\xdb\x0f\x43\x89\xeb\xb2\x71\xff\xf0\x93\x9b\x15\x09\x37\x93\xf4\x0e\x67\x84\xd5\xbd\x15\xed" + 148 | "\x70\x40\x48\x17\xb3\x13\xc5\xcb\xbb\xfd\x19\xd0\x47\x3e\xce\x94\x67\xe3\xd4\x38\x56\xa2\xbb\x1b" + 149 | "\xf7\x9b\xa0\x4a\x1d\xa6\xd8\x1b\xb8\x2e\x68\x73\x7f\x0b\xd1\x44\xc8\xbd\x90\xa2\xfb\x9e\x5e\x4f" + 150 | "\xad\xff\x82\xa3\xe9\x24\xe3\x50\x51\x63\x07\xe5\x02\xda\x46\xa1\x6a\xc2\x26\x08\x26\x63\x4f\x38" + 151 | "\x3d\xc4\x51\xd2\x7b\x77\x8d\x39\x89\xd2\x1f\x19\x7a\x02\xad\x1c\x9c\xdb\x0b\xa1\xdf\xec\x99\x1d" + 152 | "\xd0\xf6\x4a\x43\x16\xbe\x37\xd6\x1f\x1a\xd0\x26\x29\xbf\xf9\x6f\x91\x66\x64\x6b\xfa\x78\x7d\x65" + 153 | "\x6f\x1b\x36\x52\x20\x81\x18\xa4\x0b\x25\x18\xb3\xd9\x30\x37\x10\x39\x39\x8d\xd2\xf1\x96\xed\xa1" + 154 | "\x19\x7a\xf7\xee\xd2\xf0\x1d\xf6\x98\xb1\x15\x29\x60\xc4\xd0\x3d\xf8\xad\x67\x4c\xa0\xa0\x72\x57" + 155 | "\x63\x7f\xff\x52\x43\x49\x49\x1b\x2a\x00\x47\x84\x97\xe8\xd6\xfb\xfa\xf8\x74\x77\x2f\x8f\x9d\x16" + 156 | "\x79\x55\x71\xb9\x0c\x86\x44\xf0\x3b\xd5\x73\x7f\xd6\x23\x9c\xb6\x8a\xd4\xa0\x51\x2e\x1a\x5e\x74" + 157 | "\xb2\xb2\x89\x6f\x7a\xb7\x9e\x90\xd9\x47\x46\x0c\xfc\x7d\x8b\x57\xf1\xcd\x62\xea\xa9\x57\x87\xff" + 158 | "\xcd\x63\x96\xf5\x2e\xdd\xad\x0d\x1f\x54\x1d\x13\xf7\x1d\xe3\xe7\x33\x54\xa0\x2d\x8b\x40\xbd\x26" + 159 | "\xc4\xf7\x5f\x73\x97\x8e\xc4\xa6\x6a\xea\x3c\xdb\x43\x9b\x6b\x84\x9d\xa7\xd7\x5c\x1e\xbd\x72\xd6" + 160 | "\x34\x66\x46\x65\x36\x14\x80\x4b\xef\x3e\x3d\x6c\x5a\x21\x2d\x18\x2d\xe7\x41\xd5\x94\xe3\x60\x7a" + 161 | "\x7b\xfe\x37\x00\x00\xff\xff", 162 | size: 4129, 163 | mode: 0666, 164 | time: time.Unix(1529710666, 430493700), 165 | }, 166 | "template/minimal/main.js.tmpl": &asset{ 167 | name: "main.js.tmpl", 168 | data: "" + 169 | "\x94\x90\xcd\x4e\x42\x31\x10\x85\xf7\x24\xbc\xc3\xa4\xab\x7b\x13\xb9\x3c\x00\x2b\x51\x16\x26\x18" + 170 | "\x17\x3e\xc1\xd0\x0e\xbd\x95\x61\x06\xdb\xde\x46\x62\x78\x77\x53\x21\x44\x22\xd1\xb0\xea\x4f\xe6" + 171 | "\x9c\x39\xe7\x9b\x4e\x61\xa9\xe8\x12\xa4\xbd\x64\xfc\x80\x3e\xf8\x9e\x83\xef\x73\x10\x0f\x28\x0e" + 172 | "\x72\x4f\xb0\xd5\x55\x60\x02\xc1\x12\x3c\xe6\xa0\xd2\x8d\x47\x4e\xed\xb0\x25\xc9\x1d\x3a\xb7\x28" + 173 | "\x24\x79\x19\x52\x26\xa1\xd8\x98\xc7\x97\xe7\x07\x95\x5c\xff\x14\x1d\x39\x73\x07\xeb\x41\x6c\x15" + 174 | "\x36\x2d\x7c\x8e\x47\x00\x67\xf5\xfb\x40\x71\xff\x4a\x4c\x36\x6b\xbc\x67\x6e\x8c\x0b\x05\x76\x91" + 175 | "\x4c\xdb\xad\x35\x2e\xd0\xf6\xcd\x59\x5c\x90\x07\x3a\x39\x00\xf4\xfc\x96\xba\x73\xde\x39\xab\xdd" + 176 | "\x9c\x26\x66\x75\xe0\x50\x8f\x8b\x5d\x9e\xf2\x82\xa9\x5e\xe7\xfb\x27\xd7\x18\xc1\x32\x59\x0d\xd1" + 177 | "\x53\x34\xed\x95\x1a\x96\x83\xdd\x5c\xc9\xfe\x87\xe3\x11\xd4\x44\xb0\x98\xb6\xb3\x8c\x29\x55\xbb" + 178 | "\x2e\xab\xf7\x4c\xc7\x85\xba\x23\x31\xed\xf5\x80\xbf\x61\x74\x55\x62\x95\x19\x77\x89\x80\x03\xe0" + 179 | "\xff\x5c\xbe\x5f\x37\xf5\xb9\xbd\x51\xa4\xad\x96\x8b\x46\xb3\xa3\xd5\xe1\x07\xfc\x43\x3b\xfb\x0a" + 180 | "\x00\x00\xff\xff", 181 | size: 607, 182 | mode: 0666, 183 | time: time.Unix(1529800820, 581305700), 184 | }, 185 | } 186 | 187 | // AssetAndInfo loads and returns the asset and asset info for the 188 | // given name. It returns an error if the asset could not be found 189 | // or could not be loaded. 190 | func AssetAndInfo(name string) ([]byte, os.FileInfo, error) { 191 | a, ok := _bindata[filepath.ToSlash(name)] 192 | if !ok { 193 | return nil, nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist} 194 | } 195 | 196 | a.once.Do(func() { 197 | fr := flate.NewReader(strings.NewReader(a.data)) 198 | 199 | var buf bytes.Buffer 200 | if _, a.err = io.Copy(&buf, fr); a.err != nil { 201 | return 202 | } 203 | 204 | if a.err = fr.Close(); a.err == nil { 205 | a.bytes = buf.Bytes() 206 | } 207 | }) 208 | if a.err != nil { 209 | return nil, nil, &os.PathError{Op: "read", Path: name, Err: a.err} 210 | } 211 | 212 | return a.bytes, a, nil 213 | } 214 | 215 | // AssetInfo loads and returns the asset info for the given name. 216 | // It returns an error if the asset could not be found or 217 | // could not be loaded. 218 | func AssetInfo(name string) (os.FileInfo, error) { 219 | a, ok := _bindata[filepath.ToSlash(name)] 220 | if !ok { 221 | return nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist} 222 | } 223 | 224 | return a, nil 225 | } 226 | 227 | // Asset loads and returns the asset for the given name. 228 | // It returns an error if the asset could not be found or 229 | // could not be loaded. 230 | func Asset(name string) ([]byte, error) { 231 | data, _, err := AssetAndInfo(name) 232 | return data, err 233 | } 234 | 235 | // MustAsset is like Asset but panics when Asset would return an error. 236 | // It simplifies safe initialization of global variables. 237 | func MustAsset(name string) []byte { 238 | a, err := Asset(name) 239 | if err != nil { 240 | panic("asset: Asset(" + name + "): " + err.Error()) 241 | } 242 | 243 | return a 244 | } 245 | 246 | // AssetNames returns the names of the assets. 247 | func AssetNames() []string { 248 | names := make([]string, 0, len(_bindata)) 249 | for name := range _bindata { 250 | names = append(names, name) 251 | } 252 | 253 | return names 254 | } 255 | 256 | // RestoreAsset restores an asset under the given directory 257 | func RestoreAsset(dir, name string) error { 258 | return restore.Asset(dir, name, AssetAndInfo) 259 | } 260 | 261 | // RestoreAssets restores an asset under the given directory recursively 262 | func RestoreAssets(dir, name string) error { 263 | return restore.Assets(dir, name, AssetDir, AssetAndInfo) 264 | } 265 | 266 | // AssetDir returns the file names below a certain 267 | // directory embedded in the file by go-bindata. 268 | // For example if you run go-bindata on data/... and data contains the 269 | // following hierarchy: 270 | // data/ 271 | // foo.txt 272 | // img/ 273 | // a.png 274 | // b.png 275 | // then AssetDir("data") would return []string{"foo.txt", "img"} 276 | // AssetDir("data/img") would return []string{"a.png", "b.png"} 277 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error 278 | // AssetDir("") will return []string{"data"}. 279 | func AssetDir(name string) ([]string, error) { 280 | node := _bintree 281 | 282 | if name != "" { 283 | var ok bool 284 | for _, p := range strings.Split(filepath.ToSlash(name), "/") { 285 | if node, ok = node[p]; !ok { 286 | return nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist} 287 | } 288 | } 289 | } 290 | 291 | if len(node) == 0 { 292 | return nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist} 293 | } 294 | 295 | rv := make([]string, 0, len(node)) 296 | for name := range node { 297 | rv = append(rv, name) 298 | } 299 | 300 | return rv, nil 301 | } 302 | 303 | type bintree map[string]bintree 304 | 305 | var _bintree = bintree{ 306 | "template": bintree{ 307 | "minimal": bintree{ 308 | "index.html.tmpl": bintree{}, 309 | "main.css.tmpl": bintree{}, 310 | "main.js.tmpl": bintree{}, 311 | }, 312 | }, 313 | } 314 | -------------------------------------------------------------------------------- /template/minimal/index.html.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{.Meta.Title}}{{if ne .Meta.Branding.Icon ""}} 10 | {{end}} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 38 | 52 |
{{range $index, $element := .Articles}} 53 |

{{$element.Key}}

{{range $sectionIndex, $sectionElement := $element.Value}} 54 |
55 |
56 |

{{$sectionElement.Key}}

57 |
58 | {{readContent $sectionElement.Value}} 59 |
60 |
61 |
62 | {{end}}{{end}}
63 | 64 | -------------------------------------------------------------------------------- /template/minimal/main.css.tmpl: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Rubik'); 2 | @import url('https://cdn.jsdelivr.net/npm/typeface-league-spartan@0.0.44/index.min.css'); 3 | 4 | html, body { 5 | margin: 0; 6 | padding: 0; 7 | height: 100%; 8 | font-size: 100%; 9 | background-color: #{{.Background}}; 10 | font-family: Rubik, sans-serif; 11 | } 12 | 13 | .logo { 14 | margin: 0 auto 45px auto; 15 | display: block; 16 | max-width: 100px; 17 | max-height: 50px; 18 | } 19 | 20 | .sidebar { 21 | height: 100%; 22 | width: 280px; 23 | padding-top: 2.5rem; 24 | position: fixed; 25 | display: block; 26 | top: 0; 27 | left: 0; 28 | background-color: #{{.Nav}}; 29 | overflow-y: auto; 30 | box-shadow: 0 0 25px -4px rgba(0, 0, 0, 0.09); 31 | } 32 | 33 | .sidebar-content { 34 | margin-top: 4rem; 35 | } 36 | 37 | .nav-header { 38 | text-transform: uppercase; 39 | font: .6rem League Spartan, sans-serif; 40 | color: #{{.Primary}}; 41 | letter-spacing: .15em; 42 | transition: letter-spacing .2s; 43 | } 44 | 45 | .nav-header:hover { 46 | letter-spacing: .2em; 47 | } 48 | 49 | .nav-collapse { 50 | height: auto; 51 | padding: 10px 0 3px; 52 | } 53 | 54 | .nav-collapse li { 55 | padding: 4px 0 4px 15px; 56 | } 57 | 58 | .nav-collapse a { 59 | color: #{{.Secondary}}; 60 | font: .65rem League Spartan, sans-serif; 61 | } 62 | 63 | .nav-collapse a:hover { 64 | opacity: 0.7; 65 | } 66 | 67 | .dropdown-container { 68 | display: block; 69 | padding: 9px 0 0 40px; 70 | } 71 | 72 | #mobile-nav { 73 | z-index: 3; 74 | position: fixed; 75 | top: 0; 76 | left: 0; 77 | width: 100%; 78 | } 79 | 80 | .nav-content { 81 | padding-top: 15%; 82 | display: none; 83 | } 84 | 85 | .nav-open .nav-content { 86 | display: block; 87 | } 88 | 89 | .nav-open { 90 | background-color: #{{.Nav}}; 91 | height: 100%; 92 | } 93 | 94 | #nav-burger { 95 | top: 15px; 96 | left: 15px; 97 | position: fixed; 98 | width: 20px; 99 | height: 10px; 100 | z-index: 3; 101 | cursor: pointer; 102 | -webkit-transition: 0.5s ease-in-out; 103 | transition: 0.5s ease-in-out; 104 | } 105 | 106 | #nav-burger span { 107 | display: block; 108 | margin-bottom: 3px; 109 | position: absolute; 110 | height: 2px; 111 | width: 100%; 112 | background: #{{.Primary}}; 113 | border-radius: 20%; 114 | opacity: 1; 115 | left: 0; 116 | -webkit-transition: 0.25s ease-in-out; 117 | transition: 0.25s ease-in-out; 118 | } 119 | 120 | #nav-burger span:nth-child(1) { 121 | top: 0; 122 | } 123 | 124 | #nav-burger span:nth-child(2) { 125 | top: 6px; 126 | } 127 | 128 | #nav-burger span:nth-child(3) { 129 | top: 12px; 130 | } 131 | 132 | .nav-open #nav-burger span:nth-child(1) { 133 | -webkit-transform: rotate(135deg); 134 | transform: rotate(135deg); 135 | top: 6px; 136 | } 137 | 138 | .nav-open #nav-burger span:nth-child(2) { 139 | opacity: 0; 140 | left: -30px; 141 | } 142 | 143 | .nav-open #nav-burger span:nth-child(3) { 144 | -webkit-transform: rotate(-135deg); 145 | transform: rotate(-135deg); 146 | top: 6px; 147 | } 148 | 149 | article { 150 | padding-top: 2rem; 151 | } 152 | 153 | .content pre { 154 | border-radius: 0.6rem; 155 | background-size: cover; 156 | padding: 1em; 157 | margin: 1.6rem 0 1.6rem !important; 158 | -webkit-box-shadow: 0 0 38px 0 rgba(0, 0, 0, 0.2); 159 | box-shadow: 0 0 38px 0 rgba(0, 0, 0, 0.2); 160 | font-size: 1rem; 161 | } 162 | 163 | .body { 164 | height: 100%; 165 | padding: 0 6% 6% 6%; 166 | margin: 2rem 0 0 280px; 167 | display: block; 168 | } 169 | 170 | .article .content { 171 | font-size: .8rem; 172 | color: #{{.Text}}; 173 | white-space: normal; 174 | } 175 | 176 | .body-header { 177 | letter-spacing: 0.1rem; 178 | font: 1.2rem League Spartan, sans-serif; 179 | color: #{{.Primary}}; 180 | margin-bottom: 1rem; 181 | box-sizing: content-box; 182 | } 183 | 184 | .article-header { 185 | letter-spacing: 0.1rem; 186 | font: 1.6rem League Spartan, sans-serif; 187 | color: #{{.Primary}}; 188 | padding-top: 5rem; 189 | box-sizing: content-box; 190 | } 191 | 192 | .article-header:after { 193 | background: none repeat scroll 0 0 #{{.Secondary}}; 194 | top: 0.2rem; 195 | content: ""; 196 | display: block; 197 | height: 2px; 198 | position: relative; 199 | width: .8rem; 200 | border-radius: 30%; 201 | } 202 | 203 | @media screen and (max-width: 768px) { 204 | .body { 205 | padding: 0 6% 6% 6%; 206 | margin-left: 0; 207 | } 208 | } 209 | 210 | @keyframes bounce { 211 | 50% { 212 | transform: translateY(-30%); 213 | } 214 | } 215 | 216 | @-webkit-keyframes bounce { 217 | 50% { 218 | transform: translateY(-30%); 219 | } 220 | } 221 | 222 | ::-webkit-scrollbar { 223 | width: 8px; 224 | background-color: rgba(0, 0, 0, 0); 225 | -webkit-border-radius: 100px; 226 | } 227 | 228 | ::-webkit-scrollbar-thumb:vertical { 229 | background: #{{.Secondary}}; 230 | -webkit-border-radius: 100px; 231 | background-clip: padding-box; 232 | border: 2px solid rgba(0, 0, 0, 0); 233 | min-height: 10px; 234 | } -------------------------------------------------------------------------------- /template/minimal/main.js.tmpl: -------------------------------------------------------------------------------- 1 | // Loads syntax highlighting and the mobile navigation. 2 | document.addEventListener("DOMContentLoaded", function() { 3 | document.querySelectorAll("div pre").forEach(function(value) { 4 | hljs.highlightBlock(value); 5 | }); 6 | 7 | document.getElementById("nav-burger").addEventListener("click", function() { 8 | document.getElementById("mobile-nav").classList.toggle("nav-open") 9 | }); 10 | 11 | document.querySelectorAll(".nav-collapse li a").forEach(function(value) { 12 | value.addEventListener("click", function() { 13 | document.getElementById("mobile-nav").classList.remove("nav-open"); 14 | }); 15 | }); 16 | }); --------------------------------------------------------------------------------