diff options
| author | Shulhan <ms@kilabit.info> | 2020-05-01 13:30:42 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2020-05-01 13:30:42 +0700 |
| commit | 9039448f8a91ee96ecea1c7c78ccaf81f4699e92 (patch) | |
| tree | 376d09cdf6d18573ee334887b6c33a39910c501e | |
| parent | f6811267d6c7985d75f4bec491c26521e88ea514 (diff) | |
| download | ciigo-9039448f8a91ee96ecea1c7c78ccaf81f4699e92.tar.xz | |
all: embed the HTML template and the stylesheet
The parameter for template either in Convert or Generate functions or
in CLI now become pure optional, not default to "templates/html.tmpl"
anymore.
This will minimize steps for user to setup or run the library or program.
| -rw-r--r-- | cmd/ciigo/main.go | 9 | ||||
| -rw-r--r-- | content/index.adoc | 38 | ||||
| -rw-r--r-- | embedded_css.go | 218 | ||||
| -rw-r--r-- | filehtml.go | 17 | ||||
| -rw-r--r-- | generate.go | 36 | ||||
| -rw-r--r-- | htmlgenerator.go | 2 | ||||
| -rw-r--r-- | server.go | 69 | ||||
| -rw-r--r-- | template_index_html.go | 59 | ||||
| -rw-r--r-- | template_search.go (renamed from template.go) | 7 |
9 files changed, 369 insertions, 86 deletions
diff --git a/cmd/ciigo/main.go b/cmd/ciigo/main.go index ad91ff3..dd48822 100644 --- a/cmd/ciigo/main.go +++ b/cmd/ciigo/main.go @@ -14,8 +14,7 @@ // // Scan the "dir" recursively to find markup files (.adoc or .md) and convert // them into HTML files. -// The template "file" is optional, default to "templates/html.tmpl" in the -// current directory. +// The template "file" is optional, default to embedded HTML template. // // ciigo [-template <file>] [-out <file>] generate <dir> // @@ -45,8 +44,7 @@ import ( func main() { isHelp := flag.Bool("help", false, "print help") - htmlTemplate := flag.String("template", "templates/html.tmpl", - "path to HTML template") + htmlTemplate := flag.String("template", "", "path to HTML template") outputFile := flag.String("out", "ciigo_static.go", "path to output of .go generated file") address := flag.String("address", ":8080", @@ -99,8 +97,7 @@ ciigo [-template <file>] convert <dir> Scan the "dir" recursively to find markup files (.adoc or .md) and convert them into HTML files. - The template "file" is optional, default to "templates/html.tmpl" in - the current directory. + The template "file" is optional, default to embedded HTML template. ciigo [-template <file>] [-out <file>] generate <dir> diff --git a/content/index.adoc b/content/index.adoc index 3ea84ec..1dcb021 100644 --- a/content/index.adoc +++ b/content/index.adoc @@ -14,33 +14,6 @@ as markup format. == ciigo as library -This README explain how to use the ciigo as library. - - -=== Document Structure - -This software use the following directory structure and file name -conventions, - -* `cmd/<name>`: this is the program that serve the generated content. - -* `content`: the root directory of static and generated content to be - embedded and served. - This is where markup files must be saved. - Any files inside this directory, except in "content/assets", will be - ignored. - -* `content/assets`: contains static files (images, js, css) that can be - accessed by any pages using absolute path under `/assets/`. - -* `templates`: contains dynamic templates. Currently. there is only single - template: `html.tmpl`, that wrap the generated HTML. - -* All markup files inside content must have an ".adoc" or ".md" extension. - - -=== Getting Started - This section describe step by step instructions on how to build and create pages to be viewed for local development using `ciigo`. @@ -94,7 +67,7 @@ import ( ) func main() { - ciigo.Generate("./content", "cmd/mysite/static.go") + ciigo.Generate("./content", "cmd/mysite/static.go", "templates/html.tmpl") } ---- @@ -191,16 +164,15 @@ markup files, as HTML files. === Usage ---- - ciigo convert [-template <file>] <dir> +$ ciigo [-template <file>] convert <dir> ---- Scan the "dir" recursively to find markup files (.adoc or .md) and convert them into HTML files. -The template "file" is optional, default to "templates/html.tmpl" in -the current directory. +The template "file" is optional, default to embedded HTML template. ---- - ciigo generate [-template <file>] [-out <file>] <dir> +$ ciigo [-template <file>] [-out <file>] generate <dir> ---- Convert all markup files inside directory "dir" recursively and then @@ -209,7 +181,7 @@ The output file is optional, default to "ciigo_static.go" in current directory. ---- - ciigo serve [-template <file>] [-address <ip:port>] <dir> +$ ciigo [-template <file>] [-address <ip:port>] serve <dir> ---- Serve all files inside directory "dir" using HTTP server, watch diff --git a/embedded_css.go b/embedded_css.go new file mode 100644 index 0000000..35874fb --- /dev/null +++ b/embedded_css.go @@ -0,0 +1,218 @@ +// Copyright 2020, Shulhan <ms@kilabit.info>. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package ciigo + +import "html/template" + +var _embeddedCSS *template.CSS + +func embeddedCSS() *template.CSS { + if _embeddedCSS != nil { + return _embeddedCSS + } + + css := template.CSS(` +body { + margin: 0; + font-family: Arial, sans-serif; + background-color: #fff; + line-height: 1.3; + text-align: center; + color: #222; +} +pre, +code { + font-family: Menlo, monospace; + font-size: 0.875rem; +} +pre { + line-height: 1.4; + overflow-x: auto; + background: #efefef; + padding: 0.625rem; + border-radius: 0.3125rem; +} +a { + color: #007d9c; + text-decoration: none; +} +a:hover { + text-decoration: underline; +} + +p, +li { + max-width: 50rem; + word-wrap: break-word; +} +li p { + margin: 2px; +} +p, +pre, +ul, +ol { + margin: 1.25rem; +} + +h1, +h2, +h3, +h4 { + margin: 1.25rem 0 1.25rem; + padding: 0; + color: #007d9c; + font-weight: bold; +} +h1 { + font-size: 1.75rem; + line-height: 1; +} +h1 .text-muted { + color: #777; +} +h2 { + clear: right; + font-size: 1.25rem; + background: #e0ebf5; + padding: 0.5rem; + line-height: 1.25; + font-weight: normal; + overflow: auto; + overflow-wrap: break-word; +} +h2 a { + font-weight: bold; +} +h3 { + font-size: 1.25rem; + line-height: 1.25; + overflow: auto; + overflow-wrap: break-word; +} +h3, +h4 { + margin: 1.25rem 0.3125rem; +} +h4 { + font-size: 1rem; +} + +h2 > span, +h3 > span { + float: right; + margin: 0 25px 0 0; + font-weight: normal; + color: #5279c7; +} + +dl { + margin: 1.25rem; +} +dd { + margin: 0 0 0 1.25rem; +} +dl, +dd { + font-size: 0.875rem; +} + +/** + * Custom classes for pages + */ + +.topbar { + background: #e0ebf5; + height: 4rem; + overflow: hidden; +} + +.topbar .top-heading, +.topbar .menu { + padding: 1.313rem 0; + font-size: 1.25rem; + font-weight: normal; +} +.topbar .top-heading { + float: left; +} +.topbar .top-heading a { + color: #222; + text-decoration: none; +} + +.top-heading .header-logo { + height: 2rem; + width: 5.125rem; +} + +.topbar .menu { + float: right; +} +.topbar .menu a { + margin: 0.625rem 0.125rem; + padding: 0.625rem; + color: white; + background: #007d9c; + border: 0.0625rem solid #007d9c; + border-radius: 5px; +} +.topbar .menu form { + display: inline-block; +} + +.page { + width: 100%; +} + +.page > .container, +.topbar > .container, +.footer > .container { + margin-left: auto; + margin-right: auto; + padding: 0 1.25rem; + max-width: 59.38rem; +} + +.page > .container { + text-align: left; +} + +.container .meta { + font-style: italic; + margin: 1.25rem; +} + +.footer { + text-align: center; + color: #666; + font-size: 0.875rem; + margin: 2.5rem 0; +} + +/** Custom classes for asciidoc */ +#toctitle { + display: none; +} +#toc li { + list-style: none; +} +#toc ul .sectlevel1 { + padding: 0px; + margin: 4px; +} +#toc ul .sectlevel2 { + margin: 4px; +} + +@media screen and (max-width: 992px) { + #toc { + all: unset; + } +} +`) + _embeddedCSS = &css + return _embeddedCSS +} diff --git a/filehtml.go b/filehtml.go index 7eeda71..fb11eee 100644 --- a/filehtml.go +++ b/filehtml.go @@ -13,12 +13,13 @@ import ( // fileHTML represent an HTML metadata for header and its body. // type fileHTML struct { - Title string - Author string - Date string - Styles []string - Body template.HTML - Metadata map[string]string + Title string + Author string + Date string + EmbeddedCSS *template.CSS + Styles []string + Body template.HTML + Metadata map[string]string path string rawBody strings.Builder @@ -31,6 +32,7 @@ func (fhtml *fileHTML) reset() { fhtml.Title = "" fhtml.Author = "" fhtml.Date = "" + fhtml.EmbeddedCSS = nil fhtml.Styles = fhtml.Styles[:0] fhtml.Body = template.HTML("") @@ -59,6 +61,9 @@ func (fhtml *fileHTML) unpackMarkup(fa *fileMarkup) { fhtml.Metadata[k] = v.(string) } } + if len(fhtml.Styles) == 0 { + fhtml.EmbeddedCSS = embeddedCSS() + } fhtml.Body = template.HTML(fhtml.rawBody.String()) // nolint:gosec } diff --git a/generate.go b/generate.go index 9f5d9e3..b3a05c1 100644 --- a/generate.go +++ b/generate.go @@ -25,12 +25,17 @@ func Convert(dir, htmlTemplate string) { dir = "." } - b, err := ioutil.ReadFile(htmlTemplate) - if err != nil { - log.Fatal("ciigo.Convert: " + err.Error()) + contentHTML := templateIndexHTML + + if len(htmlTemplate) > 0 { + b, err := ioutil.ReadFile(htmlTemplate) + if err != nil { + log.Fatal("ciigo.Convert: " + err.Error()) + } + contentHTML = string(b) } - htmlg := newHTMLGenerator(htmlTemplate, string(b)) + htmlg := newHTMLGenerator(htmlTemplate, contentHTML) fileMarkups := listFileMarkups(dir) @@ -45,15 +50,20 @@ func Convert(dir, htmlTemplate string) { // convert them into Go file in "out". // func Generate(root, out, htmlTemplate string) { - b, err := ioutil.ReadFile(htmlTemplate) - if err != nil { - log.Fatal("ciigo.Generate: " + err.Error()) + contentHTML := templateIndexHTML + + if len(htmlTemplate) > 0 { + b, err := ioutil.ReadFile(htmlTemplate) + if err != nil { + log.Fatal("ciigo.Generate: " + err.Error()) + } + contentHTML = string(b) } - htmlg := newHTMLGenerator(htmlTemplate, string(b)) + htmlg := newHTMLGenerator(htmlTemplate, contentHTML) fileMarkups := listFileMarkups(root) - htmlg.convertFileMarkups(fileMarkups, false) + htmlg.convertFileMarkups(fileMarkups, len(htmlTemplate) == 0) mfs, err := memfs.New(nil, defExcludes, true) if err != nil { @@ -65,9 +75,11 @@ func Generate(root, out, htmlTemplate string) { log.Fatalf("ciigo.Generate: Mount %s: %s", root, err.Error()) } - _, err = mfs.AddFile(htmlTemplate) - if err != nil { - log.Fatalf("ciigo.Generate: AddFile %s: %s", htmlTemplate, err.Error()) + if len(htmlTemplate) > 0 { + _, err = mfs.AddFile(htmlTemplate) + if err != nil { + log.Fatalf("ciigo.Generate: AddFile %s: %s", htmlTemplate, err.Error()) + } } err = mfs.GoGenerate("", out, memfs.EncodingGzip) diff --git a/htmlgenerator.go b/htmlgenerator.go index 2cf5a76..c75806f 100644 --- a/htmlgenerator.go +++ b/htmlgenerator.go @@ -56,7 +56,7 @@ func newHTMLGenerator(file, content string) (htmlg *htmlGenerator) { return } -func (htmlg *htmlGenerator) loadTemplate() (err error) { +func (htmlg *htmlGenerator) reloadTemplate() (err error) { htmlg.tmpl, err = template.ParseFiles(htmlg.path) return @@ -37,7 +37,7 @@ type Server struct { // // The address parameter is optional, if not set its default to ":8080". // The htmlTemplate parameter is optional, if not set its default to -// "templates/html.tmpl" in current directory. +// embedded HTML template. // func NewServer(root, address, htmlTemplate string) (srv *Server) { var err error @@ -76,31 +76,11 @@ func NewServer(root, address, htmlTemplate string) (srv *Server) { log.Fatal("ciigo: " + err.Error()) } - htmlTemplate = filepath.Clean(htmlTemplate) + srv.initHTMLGenerator(htmlTemplate) if srv.opts.Development { - bhtml, err := ioutil.ReadFile(htmlTemplate) - if err != nil { - log.Fatal("ciigo.Convert: " + err.Error()) - } - - srv.htmlg = newHTMLGenerator(htmlTemplate, string(bhtml)) srv.fileMarkups = listFileMarkups(root) srv.htmlg.convertFileMarkups(srv.fileMarkups, false) - } else { - tmplNode, err := srv.http.Memfs.Get(htmlTemplate) - if err != nil { - log.Fatalf("ciigo.NewServer: Memfs.Get %s: %s", - htmlTemplate, err.Error()) - } - - bhtml, err := tmplNode.Decode() - if err != nil { - log.Fatalf("ciigo.NewServer: tmplNode.decode: %s", - err.Error()) - } - - srv.htmlg = newHTMLGenerator("", string(bhtml)) } return srv @@ -144,12 +124,49 @@ func (srv *Server) autoGenerate() { log.Fatal("ciigo: autoGenerate: " + err.Error()) } - _, err = libio.NewWatcher(srv.htmlg.path, 0, srv.onChangeHTMLTemplate) - if err != nil { - log.Fatal("ciigo: autoGenerate: " + err.Error()) + if len(srv.htmlg.path) > 0 { + _, err = libio.NewWatcher(srv.htmlg.path, 0, srv.onChangeHTMLTemplate) + if err != nil { + log.Fatal("ciigo: autoGenerate: " + err.Error()) + } } } +func (srv *Server) initHTMLGenerator(htmlTemplate string) { + if len(htmlTemplate) == 0 { + srv.htmlg = newHTMLGenerator("", templateIndexHTML) + return + } + + var ( + bhtml []byte + err error + htmlContent string + ) + + htmlTemplate = filepath.Clean(htmlTemplate) + + if srv.opts.Development { + bhtml, err = ioutil.ReadFile(htmlTemplate) + if err != nil { + log.Fatal("Server.initHTMLGenerator: " + err.Error()) + } + } else { + tmplNode, err := srv.http.Memfs.Get(htmlTemplate) + if err != nil { + log.Fatalf("Server.initHTMLGenerator: Memfs.Get %s: %s", + htmlTemplate, err.Error()) + } + bhtml, err = tmplNode.Decode() + if err != nil { + log.Fatal("Server.initHTMLGenerator: " + err.Error()) + } + } + + htmlContent = string(bhtml) + srv.htmlg = newHTMLGenerator("", htmlContent) +} + // // onChangeFileMarkup watch the markup files inside the "content" directory, // and re-generate them into HTML file when changed. @@ -216,7 +233,7 @@ func (srv *Server) onChangeHTMLTemplate(ns *libio.NodeState) { fmt.Println("web: recompiling HTML template ...") - err := srv.htmlg.loadTemplate() + err := srv.htmlg.reloadTemplate() if err != nil { log.Println("watchHTMLTemplate: loadTemplate: " + err.Error()) return diff --git a/template_index_html.go b/template_index_html.go new file mode 100644 index 0000000..346827c --- /dev/null +++ b/template_index_html.go @@ -0,0 +1,59 @@ +// Copyright 2020, Shulhan <ms@kilabit.info>. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package ciigo + +const templateIndexHTML = `<!DOCTYPE html> +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta name="theme-color" content="#375EAB" /> + + <title>{{.Title}}</title> + + <style> + {{.EmbeddedCSS}} + </style> + + {{- range .Styles}} + <link rel="stylesheet" href="{{.}}" /> + {{- end}} + </head> + <body> + <div class="topbar"> + <div class="container"> + <div class="top-heading"> + <a href="/">ciigo</a> + </div> + <div class="menu"> + <form class="item" action="/_internal/search"> + <input type="text" name="q" placeholder="Search" /> + </form> + </div> + </div> + </div> + + <div class="page"> + <div class="container"> + <h1>{{.Title}}</h1> + <div class="meta"> + {{.Author}} + <br /> + {{.Date}} + </div> + {{.Body}} + </div> + <!-- .container --> + </div> + <!-- .page --> + + <div class="footer"> + Copyright 2020, Shulhan <ms@kilabit.info>. All rights reserved. + <br /> + Use of this source code is governed by a BSD-style license that can be + found in the <a href="/LICENSE">LICENSE</a> file. + </div> + </body> +</html>` diff --git a/template.go b/template_search.go index 62d5d09..00e852b 100644 --- a/template.go +++ b/template_search.go @@ -1,3 +1,7 @@ +// Copyright 2020, Shulhan <ms@kilabit.info>. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + package ciigo const templateSearch = ` @@ -9,5 +13,4 @@ const templateSearch = ` {{range $result.Snippets}} <p>... {{.}} ...</p> {{end}} -{{end}} -` +{{end}}` |
