]> Nishi Git Mirror - aya.git/commitdiff
added amber and gcss compilers
authorSerge A. Zaitsev <zaitsev.serge@gmail.com>
Sat, 29 Aug 2015 15:47:16 +0000 (17:47 +0200)
committerSerge A. Zaitsev <zaitsev.serge@gmail.com>
Sat, 29 Aug 2015 15:47:16 +0000 (17:47 +0200)
testdata/sugar/.test/index.html [new file with mode: 0644]
testdata/sugar/.test/styles.css [new file with mode: 0644]
testdata/sugar/index.amber [new file with mode: 0644]
testdata/sugar/styles.gcss [new file with mode: 0644]
zs.go
zs_test.go

diff --git a/testdata/sugar/.test/index.html b/testdata/sugar/.test/index.html
new file mode 100644 (file)
index 0000000..f9cd4d7
--- /dev/null
@@ -0,0 +1,5 @@
+<html>
+       <body>
+               <p>Hello world</p>
+       </body>
+</html>
diff --git a/testdata/sugar/.test/styles.css b/testdata/sugar/.test/styles.css
new file mode 100644 (file)
index 0000000..42f29d4
--- /dev/null
@@ -0,0 +1 @@
+body{font:100% Helvetica, sans-serif;color:blue;}
\ No newline at end of file
diff --git a/testdata/sugar/index.amber b/testdata/sugar/index.amber
new file mode 100644 (file)
index 0000000..ec9948c
--- /dev/null
@@ -0,0 +1,3 @@
+html
+       body
+               p Hello world
diff --git a/testdata/sugar/styles.gcss b/testdata/sugar/styles.gcss
new file mode 100644 (file)
index 0000000..b2b4a29
--- /dev/null
@@ -0,0 +1,6 @@
+$base-font: Helvetica, sans-serif
+$main-color: blue
+
+body
+  font: 100% $base-font
+  color: $main-color
diff --git a/zs.go b/zs.go
index dc8b7d56583c727852ea13a2f308981d2c705061..171f8674ac16c8c9cca2361e4833cb45ed8c9bea 100644 (file)
--- a/zs.go
+++ b/zs.go
@@ -13,7 +13,9 @@ import (
        "strings"
        "time"
 
+       "github.com/eknkc/amber"
        "github.com/russross/blackfriday"
+       "github.com/yosssi/gcss"
 )
 
 const (
@@ -21,8 +23,12 @@ const (
        PUBDIR = ".pub"
 )
 
-type EvalFn func(args []string, vars map[string]string) (string, error)
+type Vars map[string]string
 
+type EvalFn func(args []string, vars Vars) (string, error)
+
+// Splits a string in exactly two parts by delimiter
+// If no delimiter is found - the second string is be empty
 func split2(s, delim string) (string, string) {
        parts := strings.SplitN(s, delim, 2)
        if len(parts) == 2 {
@@ -32,16 +38,22 @@ func split2(s, delim string) (string, string) {
        }
 }
 
-func md(path, s string) (map[string]string, string) {
+// Parses markdown content. Returns parsed header variables and content
+func md(path string) (Vars, string, error) {
+       b, err := ioutil.ReadFile(path)
+       if err != nil {
+               return nil, "", err
+       }
+       s := string(b)
        url := path[:len(path)-len(filepath.Ext(path))] + ".html"
-       v := map[string]string{
+       v := Vars{
                "file":   path,
                "url":    url,
                "output": filepath.Join(PUBDIR, url),
                "layout": "index.html",
        }
        if strings.Index(s, "\n\n") == -1 {
-               return map[string]string{}, s
+               return Vars{}, s, nil
        }
        header, body := split2(s, "\n\n")
        for _, line := range strings.Split(header, "\n") {
@@ -51,10 +63,10 @@ func md(path, s string) (map[string]string, string) {
        if strings.HasPrefix(v["url"], "./") {
                v["url"] = v["url"][2:]
        }
-       return v, body
+       return v, body, nil
 }
 
-func render(s string, vars map[string]string, eval EvalFn) (string, error) {
+func render(s string, vars Vars, eval EvalFn) (string, error) {
        delim_open := "{{"
        delim_close := "}}"
 
@@ -87,7 +99,8 @@ func render(s string, vars map[string]string, eval EvalFn) (string, error) {
        }
 }
 
-func env(vars map[string]string) []string {
+// Converts zs markdown variables into environment variables
+func env(vars Vars) []string {
        env := []string{"ZS=" + os.Args[0], "ZS_OUTDIR=" + PUBDIR}
        env = append(env, os.Environ()...)
        if vars != nil {
@@ -98,7 +111,9 @@ func env(vars map[string]string) []string {
        return env
 }
 
-func run(cmd string, args []string, vars map[string]string, output io.Writer) error {
+// Runs command with given arguments and variables, intercepts stderr and
+// redirects stdout into the given writer
+func run(cmd string, args []string, vars Vars, output io.Writer) error {
        var errbuf bytes.Buffer
        c := exec.Command(cmd, args...)
        c.Env = env(vars)
@@ -117,7 +132,7 @@ func run(cmd string, args []string, vars map[string]string, output io.Writer) er
        return nil
 }
 
-func eval(cmd []string, vars map[string]string) (string, error) {
+func eval(cmd []string, vars Vars) (string, error) {
        outbuf := bytes.NewBuffer(nil)
        err := run(path.Join(ZSDIR, cmd[0]), cmd[1:], vars, outbuf)
        if err != nil {
@@ -135,11 +150,10 @@ func eval(cmd []string, vars map[string]string) (string, error) {
 }
 
 func buildMarkdown(path string) error {
-       b, err := ioutil.ReadFile(path)
+       v, body, err := md(path)
        if err != nil {
                return err
        }
-       v, body := md(path, string(b))
        content, err := render(body, v, eval)
        if err != nil {
                return err
@@ -148,7 +162,7 @@ func buildMarkdown(path string) error {
        return buildPlain(filepath.Join(ZSDIR, v["layout"]), v)
 }
 
-func buildPlain(path string, vars map[string]string) error {
+func buildPlain(path string, vars Vars) error {
        b, err := ioutil.ReadFile(path)
        if err != nil {
                return err
@@ -168,6 +182,45 @@ func buildPlain(path string, vars map[string]string) error {
        return nil
 }
 
+func buildGCSS(path string) error {
+       f, err := os.Open(path)
+       if err != nil {
+               return err
+       }
+       s := strings.TrimSuffix(path, ".gcss") + ".css"
+       log.Println(s)
+       css, err := os.Create(filepath.Join(PUBDIR, s))
+       if err != nil {
+               return err
+       }
+
+       defer f.Close()
+       defer css.Close()
+
+       _, err = gcss.Compile(css, f)
+       return err
+}
+
+func buildAmber(path string, vars Vars) error {
+       a := amber.New()
+       err := a.ParseFile(path)
+       if err != nil {
+               return err
+       }
+       t, err := a.Compile()
+       if err != nil {
+               return err
+       }
+       //amber.FuncMap = amber.FuncMap
+       s := strings.TrimSuffix(path, ".amber") + ".html"
+       f, err := os.Create(filepath.Join(PUBDIR, s))
+       if err != nil {
+               return err
+       }
+       defer f.Close()
+       return t.Execute(f, vars)
+}
+
 func copyFile(path string) (err error) {
        var in, out *os.File
        if in, err = os.Open(path); err == nil {
@@ -202,10 +255,17 @@ func buildAll(once bool) {
                                }
                                ext := filepath.Ext(path)
                                if ext == ".md" || ext == ".mkd" {
-                                       log.Println("mkd: ", path)
+                                       log.Println("md: ", path)
                                        return buildMarkdown(path)
                                } else if ext == ".html" || ext == ".xml" {
-                                       return buildPlain(path, map[string]string{})
+                                       log.Println("html: ", path)
+                                       return buildPlain(path, Vars{})
+                               } else if ext == ".amber" {
+                                       log.Println("html: ", path)
+                                       return buildAmber(path, Vars{})
+                               } else if ext == ".gcss" {
+                                       log.Println("css: ", path)
+                                       return buildGCSS(path)
                                } else {
                                        log.Println("raw: ", path)
                                        return copyFile(path)
@@ -246,8 +306,7 @@ func main() {
                        log.Println("ERROR: filename expected")
                        return
                }
-               if b, err := ioutil.ReadFile(args[0]); err == nil {
-                       vars, _ := md(args[0], string(b))
+               if vars, _, err := md(args[0]); err == nil {
                        if len(args) > 1 {
                                for _, a := range args[1:] {
                                        fmt.Println(vars[a])
@@ -261,7 +320,7 @@ func main() {
                        log.Println(err)
                }
        default:
-               err := run(path.Join(ZSDIR, cmd), args, map[string]string{}, os.Stdout)
+               err := run(path.Join(ZSDIR, cmd), args, Vars{}, os.Stdout)
                if err != nil {
                        log.Println(err)
                }
index 8333de223e0e6fad365d2392cee0c0f808f0c85e..b74cbe246ab10aa05a1fb43b9ba354666eb74677 100644 (file)
@@ -3,6 +3,7 @@ package main
 import (
        "bytes"
        "fmt"
+       "io/ioutil"
        "log"
        "os"
        "os/exec"
@@ -31,14 +32,20 @@ func TestSplit2(t *testing.T) {
        }
 }
 
+func tmpfile(path, s string) string {
+       ioutil.WriteFile(path, []byte(s), 0644)
+       return path
+}
+
 func TestMD(t *testing.T) {
-       v, body := md("foo.md", `
+       defer os.Remove("foo.md")
+       v, body, _ := md(tmpfile("foo.md", `
        title: Hello, world!
        keywords: foo, bar, baz
        empty:
        bayan: [:|||:]
 
-this: is a content`)
+this: is a content`))
        if v["title"] != "Hello, world!" {
                t.Error()
        }
@@ -56,20 +63,20 @@ this: is a content`)
        }
 
        // Test empty md
-       v, body = md("foo.md", "")
+       v, body, _ = md(tmpfile("foo.md", ""))
        if len(v) != 0 || len(body) != 0 {
                t.Error(v, body)
        }
 
        // Test empty header
-       v, body = md("foo.md", "Hello")
+       v, body, _ = md(tmpfile("foo.md", "Hello"))
        if len(v) != 0 || body != "Hello" {
                t.Error(v, body)
        }
 }
 
 func TestRender(t *testing.T) {
-       eval := func(a []string, vars map[string]string) (string, error) {
+       eval := func(a []string, vars Vars) (string, error) {
                return "hello", nil
        }
        vars := map[string]string{"foo": "bar"}