summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2020-05-01 13:30:42 +0700
committerShulhan <ms@kilabit.info>2020-05-01 13:30:42 +0700
commit9039448f8a91ee96ecea1c7c78ccaf81f4699e92 (patch)
tree376d09cdf6d18573ee334887b6c33a39910c501e
parentf6811267d6c7985d75f4bec491c26521e88ea514 (diff)
downloadciigo-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.go9
-rw-r--r--content/index.adoc38
-rw-r--r--embedded_css.go218
-rw-r--r--filehtml.go17
-rw-r--r--generate.go36
-rw-r--r--htmlgenerator.go2
-rw-r--r--server.go69
-rw-r--r--template_index_html.go59
-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
diff --git a/server.go b/server.go
index a9a0fa5..762d391 100644
--- a/server.go
+++ b/server.go
@@ -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 &lt;ms@kilabit.info&gt;. 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}}`