From 9c90712446ae55ecc3c75a8a102188d1ce4178d1 Mon Sep 17 00:00:00 2001 From: shaoying Date: Mon, 22 Oct 2018 09:16:31 +0800 Subject: [PATCH] mac add aaa.right web.render --- etc/init.shy | 12 - src/contexts/aaa/aaa.go | 99 ++++++- src/contexts/cli/cli.go | 131 +++++----- src/contexts/ctx/ctx.go | 123 +++++++-- src/contexts/nfs/nfs.go | 67 +++-- src/contexts/web/web.go | 453 ++++++++++++++++++++++++++++++--- usr/library/base.js | 239 +++++++++++++---- usr/library/context.js | 235 +++-------------- usr/library/wiki.js | 211 --------------- usr/template/common/base.html | 145 ----------- usr/template/common/base.tmpl | 138 ++++++++++ usr/template/common/login.html | 94 ------- usr/template/common/main.html | 9 - usr/template/common/wiki.html | 222 ---------------- usr/template/travel.html | 431 ------------------------------- usr/template/upload.html | 163 ------------ 16 files changed, 1085 insertions(+), 1687 deletions(-) delete mode 100644 usr/library/wiki.js delete mode 100644 usr/template/common/base.html create mode 100644 usr/template/common/base.tmpl delete mode 100644 usr/template/common/login.html delete mode 100644 usr/template/common/main.html delete mode 100644 usr/template/common/wiki.html delete mode 100644 usr/template/travel.html delete mode 100644 usr/template/upload.html diff --git a/etc/init.shy b/etc/init.shy index 5bfdb1e3..a95b3d83 100644 --- a/etc/init.shy +++ b/etc/init.shy @@ -1,14 +1,2 @@ -~aaa - # login load var/login.txt -~file1 - history load var/history.txt - source etc/local.shy -~shell1 - alias import nfs - alias send send - alias open open - alias dial dial - alias pwd pwd - diff --git a/src/contexts/aaa/aaa.go b/src/contexts/aaa/aaa.go index cce25fb9..224742e0 100644 --- a/src/contexts/aaa/aaa.go +++ b/src/contexts/aaa/aaa.go @@ -69,7 +69,9 @@ func (aaa *AAA) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server return time.Unix(int64(n), 0).Format("15:03:04") }}, } - c.Configs = map[string]*ctx.Config{} + c.Configs = map[string]*ctx.Config{ + "right": &ctx.Config{Name: "right", Value: map[string]interface{}{}, Help: "用户权限"}, + } s := new(AAA) s.Context = c @@ -153,6 +155,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", } return true }, c) + if m.Results(0) { return } @@ -173,18 +176,26 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", } return true }, c) + if m.Results(0) { + m.Append("sessid", m.Result(0)) + return + } + if arg[0] == "" { return } m.Start(fmt.Sprintf("user%d", m.Capi("nuser", 1)), "密码登录", "password", arg[0]) m.Cap("password", "password", aaa.Password(arg[1]), "密码登录") + m.Append("sessid", m.Cap("sessid")) m.Echo(m.Cap("sessid")) return case 1: + m.Sess("login", nil) m.Travel(func(m *ctx.Message, n int) bool { if n > 0 && m.Cap("sessid") == arg[0] { if int64(m.Capi("expire_time")) > time.Now().Unix() { + m.Sess("login", m.Target().Message()) m.Echo(m.Cap("stream")) } else { m.Target().Close(m) @@ -205,6 +216,92 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", } } }}, + "right": &ctx.Command{Name: "right [user [check|owner|share group [order] [add|del]]]", Form: map[string]int{"from": 1}, Help: "权限管理", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + m.Travel(func(m *ctx.Message, n int) bool { + if n == 0 { + return true + } + if len(arg) == 0 { + m.Add("append", "user", m.Cap("stream")) + m.Add("append", "right", m.Confv("right")) + return true + } + if m.Cap("stream") == arg[0] { + if len(arg) == 1 { //查看所有权 + for k, v := range m.Confv("right").(map[string]interface{}) { + m.Add("append", "group", k) + m.Add("append", "right", v) + } + return true + } + if arg[1] == "check" { //权限检查 + if from := m.Confv("right", []interface{}{"right", "role"}); from != nil && from.(string) == "root" { + m.Echo("root") + } + if len(arg) == 2 { + return false + } + if from := m.Confv("right", []interface{}{arg[2], "right", "role"}); from != nil && from.(string) == "owner" { + m.Echo("owner") + } + if len(arg) == 3 { + return false + } + if from := m.Confv("right", []interface{}{arg[2], arg[3], "right", "role"}); from != nil && from.(string) == "share" { + m.Echo("share") + } + return false + } + if len(arg) == 2 { //分配人事权 + if m.Option("from") != "root" { + return false + } + switch arg[1] { + case "add": + m.Confv("right", []interface{}{"right", "role"}, "root") + m.Confv("right", []interface{}{"right", "from"}, m.Option("from")) + case "del": + m.Confv("right", []interface{}{"right", "role"}, "") + } + return true + } + if len(arg) == 3 { //查看使用权 + for k, v := range m.Confv("right", arg[2]).(map[string]interface{}) { + m.Add("append", "order", k) + m.Add("append", "right", v) + } + return true + } + switch arg[1] { + case "owner": //分配所有权 + if m.Cmd("right", m.Option("from"), "check").Result(0) == "" { + return false + } + switch arg[3] { + case "add": + m.Confv("right", []interface{}{arg[2], "right", "role"}, "owner") + m.Confv("right", []interface{}{arg[2], "right", "from"}, m.Option("from")) + case "del": + m.Confv("right", []interface{}{arg[2], "right", "role"}, "") + } + case "share": //分配使用权 + if m.Cmd("right", m.Option("from"), "check", arg[2]).Result(0) == "" { + return false + } + switch arg[4] { + case "add": + m.Confv("right", []interface{}{arg[2], arg[3], "right", "role"}, "share") + m.Confv("right", []interface{}{arg[2], arg[3], "right", "from"}, m.Option("from")) + case "del": + m.Confv("right", []interface{}{arg[2], arg[3], "right", "role"}, "") + } + } + return false + } + return true + }, c) + m.Table() + }}, "cert": &ctx.Command{Name: "cert [filename]", Help: "导出证书", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.certificate != nil { certificate := string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: aaa.certificate.Raw})) diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 09596344..5420c38d 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -1,20 +1,16 @@ -package cli // {{{ -// }}} -import ( // {{{ - "contexts/ctx" +package cli +import ( + "contexts/ctx" "fmt" + "os" + "os/exec" "regexp" "strconv" "strings" - - "os" - "os/exec" "time" ) -// }}} - type Frame struct { key string run bool @@ -22,7 +18,6 @@ type Frame struct { index int list []string } - type CLI struct { alias map[string][]string label map[string]string @@ -33,7 +28,7 @@ type CLI struct { *ctx.Context } -func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ +func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { c.Caches = map[string]*ctx.Cache{ "level": &ctx.Cache{Name: "level", Value: "0", Help: "嵌套层级"}, "parse": &ctx.Cache{Name: "parse(true/false)", Value: "true", Help: "命令解析"}, @@ -43,15 +38,15 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server } c.Configs = map[string]*ctx.Config{ "ps_time": &ctx.Config{Name: "ps_time", Value: "[15:04:05]", Help: "当前时间", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { - if len(arg) > 0 { // {{{ + if len(arg) > 0 { return arg[0] } return time.Now().Format(x.Value.(string)) - // }}} + }}, "ps_end": &ctx.Config{Name: "ps_end", Value: "> ", Help: "命令行提示符结尾"}, "prompt": &ctx.Config{Name: "prompt(ps_count/ps_time/ps_target/ps_end/...)", Value: "ps_count ps_time ps_target ps_end", Help: "命令行提示符, 以空格分隔, 依次显示缓存或配置信息", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { - if len(arg) > 0 { // {{{ + if len(arg) > 0 { return arg[0] } @@ -64,7 +59,7 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server } } return strings.Join(ps, "") - // }}} + }}, } @@ -83,15 +78,11 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server return s } - -// }}} -func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ +func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { cli.Message = m return cli } - -// }}} -func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{ +func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { cli.Message = m m.Sess("cli", m) yac := m.Sess("yac") @@ -178,9 +169,7 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{ } return false } - -// }}} -func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { // {{{ +func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { switch cli.Context { case m.Target(): case m.Source(): @@ -188,8 +177,6 @@ func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { // {{{ return true } -// }}} - var Pulse *ctx.Message var Index = &ctx.Context{Name: "cli", Help: "管理中心", Caches: map[string]*ctx.Cache{ @@ -199,11 +186,11 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", "init.shy": &ctx.Config{Name: "init.shy", Value: "etc/init.shy", Help: "启动脚本"}, "exit.shy": &ctx.Config{Name: "exit.shy", Value: "etc/exit.shy", Help: "启动脚本"}, "cli_name": &ctx.Config{Name: "cli_name", Value: "shell", Help: "模块命名", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { - if len(arg) > 0 { // {{{ + if len(arg) > 0 { return arg[0] } return fmt.Sprintf("%s%d", x.Value, m.Capi("nshell", 1)) - // }}} + }}, "cli_help": &ctx.Config{Name: "cli_help", Value: "shell", Help: "模块文档"}, "cmd_timeout": &ctx.Config{Name: "cmd_timeout", Value: "60s", Help: "系统命令超时"}, @@ -239,28 +226,28 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } }}, "label": &ctx.Command{Name: "label name", Help: "记录当前脚本的位置, name: 位置名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { if cli.label == nil { cli.label = map[string]string{} } cli.label[arg[1]] = m.Option("file_pos") - } // }}} + } }}, "goto": &ctx.Command{Name: "goto label [exp] condition", Help: "向上跳转到指定位置, label: 跳转位置, condition: 跳转条件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { if pos, ok := cli.label[arg[1]]; ok { if !ctx.Right(arg[len(arg)-1]) { return } m.Append("file_pos0", pos) } - } // }}} + } }}, "return": &ctx.Command{Name: "return result...", Help: "结束脚本, result: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { m.Add("append", "return", arg[1:]) }}, "target": &ctx.Command{Name: "target module", Help: "设置当前模块, module: 模块全名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { if len(arg) == 0 { m.Echo("%s", m.Cap("ps_target")) return @@ -269,13 +256,13 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", cli.target = msg.Target() m.Cap("ps_target", cli.target.Name) } - } // }}} + } }}, "alias": &ctx.Command{ Name: "alias [short [long...]]|[delete short]|[import module [command [alias]]]", Help: "查看、定义或删除命令别名, short: 命令别名, long: 命令原名, delete: 删除别名, import导入模块所有命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { switch len(arg) { case 0: for k, v := range cli.alias { @@ -318,21 +305,21 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Log("info", "%s: %v", arg[0], cli.alias[arg[0]]) } } - } // }}} + } }}, "sleep": &ctx.Command{Name: "sleep time", Help: "睡眠, time(ns/us/ms/s/m/h): 时间值(纳秒/微秒/毫秒/秒/分钟/小时)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if d, e := time.ParseDuration(arg[0]); m.Assert(e) { // {{{ + if d, e := time.ParseDuration(arg[0]); m.Assert(e) { m.Log("info", "sleep %v", d) time.Sleep(d) m.Log("info", "sleep %v done", d) - } // }}} + } }}, "time": &ctx.Command{ Name: "time [time_format format] [parse when] when [begin|end|yestoday|tommorow|monday|sunday|first|last|origin|last]", Form: map[string]int{"time_format": 1, "parse": 1, "time_interval": 1}, Help: "查看时间, time_format: 输出或解析的时间格式, parse: 输入的时间字符串, when: 输入的时间戳, 其它是时间偏移", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - t := time.Now() // {{{ + t := time.Now() if m.Options("parse") { n, e := time.ParseInLocation(m.Confx("time_format"), m.Option("parse"), time.Local) m.Assert(e) @@ -341,7 +328,6 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", if len(arg) > 0 { if i, e := strconv.ParseInt(arg[0], 10, 64); e == nil { - m.Option("time_format", m.Conf("time_format")) t = time.Unix(int64(i/int64(m.Confi("time_unit"))), 0) arg = arg[1:] } else if n, e := time.ParseInLocation(m.Confx("time_format"), arg[0], time.Local); e == nil { @@ -405,7 +391,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } else { m.Echo(t.Format(m.Confx("time_format"))) } - // }}} + }}, "echo": &ctx.Command{Name: "echo arg...", Help: "函数调用, name: 函数名, arg: 参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { m.Echo("%s", strings.Join(arg, "")) @@ -415,7 +401,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Echo(arg[0][1 : len(arg[0])-1]) }}, "exe": &ctx.Command{Name: "exe $ ( cmd )", Help: "解析嵌套命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { switch len(arg) { case 1: m.Echo(arg[0]) @@ -438,7 +424,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } //}}} }}, "val": &ctx.Command{Name: "val exp", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - result := "false" // {{{ + result := "false" switch len(arg) { case 0: result = "" @@ -567,7 +553,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } } m.Echo(result) - // }}} + }}, "exp": &ctx.Command{Name: "exp word", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if len(arg) > 0 && arg[0] == "{" { @@ -585,7 +571,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", return } - pre := map[string]int{ // {{{ + pre := map[string]int{ "=": 1, "+": 2, "-": 2, "*": 3, "/": 3, "%": 3, @@ -609,10 +595,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } m.Echo("%s", num[0]) - // }}} + }}, "var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 1 { // {{{ + if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 1 { switch arg[2] { case "=": m.Cap(arg[1], arg[3]) @@ -621,28 +607,28 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } } m.Echo(m.Cap(arg[1])) - // }}} + }}, "let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式(a {+|-|*|/|%} b)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - switch arg[2] { // {{{ + switch arg[2] { case "=": m.Cap(arg[1], arg[3]) case "<-": m.Cap(arg[1], m.Cap("last_msg")) } m.Echo(m.Cap(arg[1])) - // }}} + }}, "if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { run := m.Caps("parse") && ctx.Right(arg[1]) cli.stack = append(cli.stack, &Frame{pos: m.Optioni("file_pos"), key: key, run: run}) m.Capi("level", 1) m.Caps("parse", run) - } // }}} + } }}, "else": &ctx.Command{Name: "else", Help: "条件语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { if !m.Caps("parse") { m.Caps("parse", true) } else { @@ -653,10 +639,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Caps("parse", !frame.run) } } - } // }}} + } }}, "end": &ctx.Command{Name: "end", Help: "结束语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { if frame := cli.stack[len(cli.stack)-1]; frame.key == "for" && frame.run { m.Append("file_pos0", frame.pos) return @@ -667,13 +653,13 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } else { m.Caps("parse", true) } - } // }}} + } }}, "for": &ctx.Command{ Name: "for [[express ;] condition]|[index message meta value]", Help: "循环语句, express: 每次循环运行的表达式, condition: 循环条件, index: 索引消息, message: 消息编号, meta: value: ", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { run := m.Caps("parse") defer func() { m.Caps("parse", run) }() @@ -726,10 +712,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } m.Cap(arg[3], arg[3], frame.list[0], "临时变量") } - } // }}} + } }}, "cmd": &ctx.Command{Name: "cmd word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{ + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { detail := []string{} if a, ok := cli.alias[arg[0]]; ok { detail = append(detail, a...) @@ -774,14 +760,14 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Capi("last_msg", 0, msg.Code()) m.Capi("ps_count", 1) } - // }}} + }}, "system": &ctx.Command{ Name: "system [cmd_combine true|false] [cmd_timeout time] word...", Help: "调用系统命令, cmd_combine: 非交互式命令, cmd_timeout: 命令超时, word: 命令", Form: map[string]int{"cmd_combine": 1, "cmd_timeout": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - system := map[string]bool{"vi": true} // {{{ + system := map[string]bool{"vi": true} ui, ok := system[arg[0]] if ui = ok && ui; m.Option("cmd_combine") != "" { ui = !m.Options("cmd_combine") @@ -816,7 +802,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", case <-wait: } } - // }}} + }}, "login": &ctx.Command{Name: "login username password", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { m.Sess("aaa", false).Cmd("login", arg[0], arg[1]) @@ -827,6 +813,27 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", "tmux": &ctx.Command{Name: "tmux", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { m.Copy(m.Spawn().Cmd("system", "tmux", arg), "result") }}, + "buffer": &ctx.Command{Name: "buffer", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + bufs := strings.Split(m.Spawn().Cmd("system", "tmux", "list-buffers").Result(0), "\n") + + n := 3 + if m.Option("limit") != "" { + n = m.Optioni("limit") + } + + for i, b := range bufs { + if i >= n { + break + } + bs := strings.SplitN(b, ": ", 3) + if len(bs) > 1 { + m.Add("append", "buffer", bs[0][:len(bs[0])]) + m.Add("append", "length", bs[1][:len(bs[1])-6]) + m.Add("append", "string", bs[2][1:len(bs[2])-1]) + } + } + m.Echo(m.Append("string")) + }}, }, Index: map[string]*ctx.Context{ "void": &ctx.Context{Caches: map[string]*ctx.Cache{"nshell": &ctx.Cache{}}}, diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index 2544921a..b5abe2ca 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -709,7 +709,14 @@ func (m *Message) Search(key string, root ...bool) []*Message { } func (m *Message) Sess(key string, arg ...interface{}) *Message { spawn := true - if _, ok := m.Sessions[key]; !ok && len(arg) > 0 { + if len(arg) > 0 { + switch v := arg[0].(type) { + case bool: + spawn, arg = v, arg[1:] + } + } + + if len(arg) > 0 { if m.Sessions == nil { m.Sessions = make(map[string]*Message) } @@ -747,13 +754,9 @@ func (m *Message) Sess(key string, arg ...interface{}) *Message { m.Sessions[key] = m.Search(value, root)[0] } return m.Sessions[key] - } - } - - if len(arg) > 0 { - switch v := arg[0].(type) { - case bool: - spawn = v + case nil: + m.Sessions[key] = nil + return nil } } @@ -1077,6 +1080,14 @@ func (m *Message) Sort(key string, arg ...string) *Message { for j := i + 1; j < len(table); j++ { result := false switch cmp { + case "str": + if table[i][key] > table[j][key] { + result = true + } + case "str_r": + if table[i][key] < table[j][key] { + result = true + } case "int": a, e := strconv.Atoi(table[i][key]) m.Assert(e) @@ -1093,14 +1104,6 @@ func (m *Message) Sort(key string, arg ...string) *Message { if a < b { result = true } - case "string": - if table[i][key] > table[j][key] { - result = true - } - case "string_r": - if table[i][key] < table[j][key] { - result = true - } case "time": ti, e := time.ParseInLocation(m.Confx("time_layout"), table[i][key], time.Local) m.Assert(e) @@ -1964,16 +1967,18 @@ var CGI = template.FuncMap{ m.Assert(e) index = i } + if len(arg) == 2 { return m.Detail(index) } + return m.Detail(index, arg[2]) case map[string][]string: return strings.Join(m["detail"], "") case []string: return strings.Join(m, "") default: - return fmt.Sprintf("%v", arg[0]) + return m } return "" }, @@ -2016,7 +2021,7 @@ var CGI = template.FuncMap{ case []string: return strings.Join(m, "") default: - return fmt.Sprintf("%v", arg[0]) + return m } return "" }, @@ -2040,16 +2045,18 @@ var CGI = template.FuncMap{ m.Assert(e) index = i } + if len(arg) == 2 { return m.Result(index) } + return m.Result(index, arg[2]) case map[string][]string: return strings.Join(m["result"], "") case []string: return strings.Join(m, "") default: - return fmt.Sprintf("%v", arg[0]) + return m } return "" }, @@ -2092,11 +2099,55 @@ var CGI = template.FuncMap{ case []string: return strings.Join(m, "") default: - return fmt.Sprintf("%v", arg[0]) + return m } return "" }, - "unscaped": func(str string) interface{} { + "table": func(arg ...interface{}) []interface{} { + if len(arg) == 0 { + return []interface{}{} + } + + switch m := arg[0].(type) { + case *Message: + if len(m.Meta["append"]) == 0 { + return []interface{}{} + } + if len(arg) == 1 { + data := []interface{}{} + nrow := len(m.Meta[m.Meta["append"][0]]) + for i := 0; i < nrow; i++ { + line := map[string]string{} + for _, k := range m.Meta["append"] { + line[k] = m.Meta[k][i] + if len(m.Meta[k]) != i { + continue + } + } + data = append(data, line) + } + + return data + } + case map[string][]string: + if len(arg) == 1 { + data := []interface{}{} + nrow := len(m[m["append"][0]]) + + for i := 0; i < nrow; i++ { + line := map[string]string{} + for _, k := range m["append"] { + line[k] = m[k][i] + } + data = append(data, line) + } + + return data + } + } + return []interface{}{} + }, + "unescape": func(str string) interface{} { return template.HTML(str) }, @@ -2978,7 +3029,8 @@ var Index = &Context{Name: "ctx", Help: "模块中心", "where_field": 1, "where_value": 1, "sort_field": 1, "sort_order": 1, "page_limit": 1, "page_offset": 1, - "select": 3, + "format_field": 2, + "select": 3, }, Hand: func(m *Message, c *Context, key string, arg ...string) { offset, e := strconv.Atoi(m.Confx("page_offset")) @@ -3022,6 +3074,12 @@ var Index = &Context{Name: "ctx", Help: "模块中心", de.Decode(&save) } + format_field := m.Option("format_field") + format_str := "%s" + if format_field != "" { + format_str = m.Meta["format_field"][1] + } + // sort_field := m.Option("sort_field") // sort_order := m.Option("sort_order") m.BackTrace(func(m *Message) bool { @@ -3113,7 +3171,11 @@ var Index = &Context{Name: "ctx", Help: "模块中心", m.Add("append", "index", "0") for k, v := range val { if len(fields) == 0 || fields[k] { - m.Add("append", k, v) + if k == format_field { + m.Add("append", k, fmt.Sprintf(format_str, v)) + } else { + m.Add("append", k, v) + } } } case []interface{}: @@ -3134,7 +3196,11 @@ var Index = &Context{Name: "ctx", Help: "模块中心", m.Add("append", "index", i) for k, v := range val { if len(fields) == 0 || fields[k] { - m.Add("append", k, v) + if k == format_field { + m.Add("append", k, fmt.Sprintf(format_str, v, v)) + } else { + m.Add("append", k, v) + } } } } @@ -3142,11 +3208,18 @@ var Index = &Context{Name: "ctx", Help: "模块中心", case []string: for i, v := range val { m.Add("append", "index", i) - m.Add("append", "value", v) + if k == format_field { + m.Add("append", k, fmt.Sprintf(format_str, v, v)) + } else { + m.Add("append", k, v) + } } default: m.Echo("%v", Trans(val)[0]) } + case 3: + m.Echo("%v", m.Confv(arg[0], strings.Split(arg[1], "."), arg[2])) + default: m.Echo("%v", m.Confv(arg[0], arg[1:])) return false diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index c864bc6f..7904ec3e 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -68,8 +68,8 @@ func dir(m *ctx.Message, name string, level int, deep bool, fields []string) { switch k { case "filename": m.Add("append", "filename", "..") - case "dir": - m.Add("append", "dir", "true") + case "is_dir": + m.Add("append", "is_dir", "true") case "size": m.Add("append", "size", 0) case "line": @@ -130,8 +130,8 @@ func dir(m *ctx.Message, name string, level int, deep bool, fields []string) { switch k { case "filename": m.Add("append", "filename", filename) - case "dir": - m.Add("append", "dir", f.IsDir()) + case "is_dir": + m.Add("append", "is_dir", f.IsDir()) case "size": m.Add("append", "size", f.Size()) case "line": @@ -803,11 +803,12 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", "buf_size": &ctx.Config{Name: "buf_size", Value: "1024", Help: "读取文件的缓存区的大小"}, "qr_size": &ctx.Config{Name: "qr_size", Value: "256", Help: "生成二维码的图片的大小"}, - "dir_name": &ctx.Config{Name: "dir_name(name/tree/path/full)", Value: "name", Help: "dir命令输出文件名的类型, name: 文件名, tree: 带缩进的文件名, path: 相对路径, full: 绝对路径"}, - "dir_info": &ctx.Config{Name: "dir_info(sizes/lines/files/dirs)", Value: "sizes lines files dirs", Help: "dir命令输出目录的统计信息, info: 输出统计信息, 否则输出"}, + "dir_root": &ctx.Config{Name: "dir_root", Value: "usr", Help: "dir命令输出目录的统计信息, info: 输出统计信息, 否则输出"}, "dir_deep": &ctx.Config{Name: "dir_deep(yes/no)", Value: "yes", Help: "dir命令输出目录的统计信息, info: 输出统计信息, 否则输出"}, "dir_type": &ctx.Config{Name: "dir_type(file/dir)", Value: "file", Help: "dir命令输出的文件类型, file: 只输出普通文件, dir: 只输出目录文件, 否则输出所有文件"}, - "dir_field": &ctx.Config{Name: "dir_field", Value: "filename line size time", Help: "表格排序字段"}, + "dir_name": &ctx.Config{Name: "dir_name(name/tree/path/full)", Value: "name", Help: "dir命令输出文件名的类型, name: 文件名, tree: 带缩进的文件名, path: 相对路径, full: 绝对路径"}, + "dir_info": &ctx.Config{Name: "dir_info(sizes/lines/files/dirs)", Value: "sizes lines files dirs", Help: "dir命令输出目录的统计信息, info: 输出统计信息, 否则输出"}, + "dir_field": &ctx.Config{Name: "dir_field", Value: "filename is_dir line size time", Help: "表格排序字段"}, "sort_field": &ctx.Config{Name: "sort_field", Value: "line", Help: "表格排序字段"}, "sort_order": &ctx.Config{Name: "sort_order(int/int_r/string/string_r/time/time_r)", Value: "int", Help: "表格排序类型"}, @@ -1078,13 +1079,16 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", if len(arg) == 1 { var data interface{} e := json.Unmarshal([]byte(arg[0]), &data) + if e != nil { + return + } m.Assert(e) buf, e := json.MarshalIndent(data, "", " ") m.Assert(e) - m.Echo("'") + // m.Echo("'") m.Echo(string(buf)) - m.Echo("'") + // m.Echo("'") return } @@ -1122,10 +1126,6 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", "pwd": &ctx.Command{Name: "pwd", Help: "查看当前路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if m.Options("dir") { m.Echo(m.Option("dir")) - m.Add("append", "hi", "hello") - m.Add("append", "he", "hello") - m.Add("append", "hi", "world") - m.Add("append", "he", "world") return } if len(arg) > 0 { @@ -1134,20 +1134,31 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", wd, e := os.Getwd() m.Assert(e) m.Echo(wd) - m.Append("hi", "hello") }}, "dir": &ctx.Command{ - Name: "dir dir [dir_deep yes|no] [dir_info info] [dir_name name|tree|path|full] [dir_type file|dir] [sort_field name] [sort_order type]", + Name: "dir dir [dir_deep yes|no] [dir_info info] [dir_name name|tree|path|full] [dir_type both|file|dir] [sort_field name] [sort_order type]", Help: "查看目录, dir: 目录名, dir_info: 显示统计信息, dir_name: 文件名类型, dir_type: 文件类型, sort_field: 排序字段, sort_order: 排序类型", - Form: map[string]int{"dir_field": 1, "dir_deep": 1, "dir_info": 1, "dir_name": 1, "dir_type": 1, "sort_field": 1, "sort_order": 1}, + Form: map[string]int{ + "dir_root": 1, + "dir_deep": 1, + "dir_type": 1, + "dir_name": 1, + "dir_info": 1, + "dir_link": 1, + "dir_field": 1, + "sort_field": 1, + "sort_order": 1, + }, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - d := "./" + m.Option("dir") if len(arg) > 0 { - d = arg[0] + m.Option("dir", arg[0]) } + m.Option("dir", path.Clean(m.Option("dir"))) + d := path.Join(m.Confx("dir_root"), m.Option("dir")) if s, e := os.Stat(d); m.Assert(e) && !s.IsDir() { d = path.Dir(d) } + fields := strings.Split(m.Confx("dir_field"), " ") trip := 0 @@ -1170,22 +1181,30 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", key := m.Meta["append"][i] switch key { case "filename": + v = maps[key] if line > -1 && trip > 0 && trip <= len(v) { v = v[trip:] - m.Meta["filename"][line] = v + if m.Options("dir_link") { + m.Meta["filename"][line] = fmt.Sprintf(m.Option("dir_link"), maps["is_dir"], v) + } else { + m.Meta["filename"][line] = v + } + } + if line > -1 { + if m.Options("dir_link") { + m.Meta["filename"][line] = fmt.Sprintf(m.Option("dir_link"), maps["is_dir"], v) + } } - case "dir": - continue } - m.Echo("%s\t", v) } - m.Echo("\n") return true }) + if !m.Options("dir_link") { + m.Table() + } for _, v := range info { m.Echo("%s: %s\n", v, m.Option(v)) } - }}, "git": &ctx.Command{ Name: "git branch|status|diff|log|info arg... [dir path]...", diff --git a/src/contexts/web/web.go b/src/contexts/web/web.go index 4d9c22d7..4536944f 100644 --- a/src/contexts/web/web.go +++ b/src/contexts/web/web.go @@ -27,8 +27,8 @@ type MUX interface { type WEB struct { *http.Client *http.ServeMux - *http.Server - *template.Template + server *http.Server + template *template.Template *ctx.Context } @@ -80,7 +80,9 @@ func (web *WEB) HandleCmd(m *ctx.Message, key string, cmd *ctx.Command) { m.TryCatch(m.Spawn(), true, func(msg *ctx.Message) { msg.Add("option", "method", r.Method).Add("option", "path", r.URL.Path) + msg.Option("remote_addr", r.RemoteAddr) msg.Option("referer", r.Header.Get("Referer")) + msg.Option("accept", r.Header.Get("Accept")) if r.ParseForm(); len(r.PostForm) > 0 { for k, v := range r.PostForm { @@ -101,11 +103,11 @@ func (web *WEB) HandleCmd(m *ctx.Message, key string, cmd *ctx.Command) { switch { case msg.Has("redirect"): - http.Redirect(w, r, msg.Append("redirect"), http.StatusFound) + http.Redirect(w, r, msg.Append("redirect"), http.StatusTemporaryRedirect) case msg.Has("directory"): http.ServeFile(w, r, msg.Append("directory")) - case msg.Has("template"): - msg.Spawn().Cmd("/render", msg.Meta["template"]) + case msg.Has("componet"): + msg.Spawn().Add("option", "componet_group", msg.Meta["componet"]).Cmd("/render") case msg.Has("append"): meta := map[string]interface{}{} if len(msg.Meta["result"]) > 0 { @@ -208,16 +210,16 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { web.Caches["protocol"] = &ctx.Cache{Name: "protocol", Value: m.Confx("protocol", arg, 2), Help: "服务协议"} web.Caches["address"] = &ctx.Cache{Name: "address", Value: m.Confx("address", arg, 1), Help: "服务地址"} m.Log("info", "%d %s://%s", m.Capi("nserve", 1), m.Cap("protocol"), m.Cap("stream", m.Cap("address"))) - web.Server = &http.Server{Addr: m.Cap("address"), Handler: web} + web.server = &http.Server{Addr: m.Cap("address"), Handler: web} if m.Caps("master", true); m.Cap("protocol") == "https" { web.Caches["cert"] = &ctx.Cache{Name: "cert", Value: m.Confx("cert", arg, 3), Help: "服务证书"} web.Caches["key"] = &ctx.Cache{Name: "key", Value: m.Confx("key", arg, 4), Help: "服务密钥"} m.Log("info", "cert [%s]", m.Cap("cert")) m.Log("info", "key [%s]", m.Cap("key")) - web.Server.ListenAndServeTLS(m.Cap("cert"), m.Cap("key")) + web.server.ListenAndServeTLS(m.Cap("cert"), m.Cap("key")) } else { - web.Server.ListenAndServe() + web.server.ListenAndServe() } return true } @@ -244,16 +246,192 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", "cert": &ctx.Config{Name: "cert", Value: "etc/cert.pem", Help: "路由数量"}, "key": &ctx.Config{Name: "key", Value: "etc/key.pem", Help: "路由数量"}, - "template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template", Help: "路由数量"}, - "template_file": &ctx.Config{Name: "template_file", Value: "usr/template", Help: "路由数量"}, - "template": &ctx.Config{Name: "template", Value: map[string]interface{}{ - "index": []interface{}{ + "web_site": &ctx.Config{Name: "web_site", Value: []interface{}{ + map[string]interface{}{"_name": "MDN", "site": "https://developer.mozilla.org"}, + map[string]interface{}{"_name": "github", "site": "https://github.com"}, + }, Help: "web_site"}, + "template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template", Help: "模板路径"}, + + "componet_context": &ctx.Config{Name: "component_context", Value: "nfs", Help: "默认模块"}, + "componet_command": &ctx.Config{Name: "component_command", Value: "pwd", Help: "默认命令"}, + "componet_group": &ctx.Config{Name: "component_group", Value: "index", Help: "默认组件"}, + "componet": &ctx.Config{Name: "componet", Value: map[string]interface{}{ + "login": []interface{}{ map[string]interface{}{ - "name": "message", "title": "message", - "context": "nfs", "command": "pwd", + "template": "head", "name": "head", "help": "head", + "context": "", "command": "", "arguments": []interface{}{}, + }, + map[string]interface{}{ + "template": "componet", "name": "login", "help": "login", + "context": "aaa", "command": "login", "arguments": []interface{}{"@username", "@password"}, + "inputs": []interface{}{ + map[string]interface{}{ + "type": "text", "name": "username", + "label": "username", "value": "", + }, + map[string]interface{}{ + "type": "password", "name": "password", + "label": "password", "value": "", + }, + map[string]interface{}{ + "type": "button", "name": "string", + "label": "string", "value": "login", + }, + }, + "display_append": "", + "display_result": "", + "result_reload": "10", + }, + map[string]interface{}{ + "template": "tail", "name": "tail", "help": "tail", + "context": "", "command": "", "arguments": []interface{}{}, }, }, - }, Help: "路由数量"}, + "index": []interface{}{ + map[string]interface{}{ + "template": "head", "name": "head", "help": "head", + "context": "", "command": "", "arguments": []interface{}{}, + }, + map[string]interface{}{ + "template": "clipboard", "name": "clipbaord", "help": "clipbaord", + "context": "", "command": "", "arguments": []interface{}{}, + }, + map[string]interface{}{ + "template": "componet", "name": "message", "help": "message", + "context": "cli", "command": "buffer", "arguments": []interface{}{}, + "inputs": []interface{}{ + map[string]interface{}{ + "type": "text", "name": "limit", + "label": "limit", "value": "3", + }, + map[string]interface{}{ + "type": "button", "name": "string", + "label": "string", "value": "refresh", + }, + }, + }, + map[string]interface{}{ + "template": "componet", "name": "time", "help": "time", + "context": "cli", "command": "time", + "arguments": []interface{}{"@string"}, + "inputs": []interface{}{ + map[string]interface{}{ + "type": "text", "name": "time_format", + "label": "format", "value": "2006-01-02 15:04:05", + }, + map[string]interface{}{ + "type": "text", "name": "string", + "label": "string", "value": "", + }, + map[string]interface{}{ + "type": "button", "name": "button", + "label": "string", "value": "refresh", + }, + }, + }, + map[string]interface{}{ + "template": "componet", "name": "json", "help": "json", + "context": "nfs", "command": "json", + "arguments": []interface{}{"@string"}, + "inputs": []interface{}{ + map[string]interface{}{ + "type": "text", "name": "string", + "label": "string", "value": "", + }, + map[string]interface{}{ + "type": "button", "name": "button", + "label": "string", "value": "refresh", + }, + }, + }, + map[string]interface{}{ + "template": "componet", "name": "dir", "help": "dir", + "context": "nfs", "command": "dir", + "arguments": []interface{}{"@dir", + "dir_deep", "no", + "dir_name", "name", + "dir_link", "%s", + "dir_info", "", + }, + "inputs": []interface{}{ + map[string]interface{}{ + "type": "text", "name": "dir", + "label": "dir", "value": "", + }, + map[string]interface{}{ + "type": "choice", "name": "dir_type", + "label": "dir_type", "value": "both", + "choice": []interface{}{ + map[string]interface{}{ + "name": "both", "value": "both", + }, + map[string]interface{}{ + "name": "file", "value": "file", + }, + map[string]interface{}{ + "name": "dir", "value": "dir", + }, + }, + }, + map[string]interface{}{ + "type": "choice", "name": "sort_field", + "label": "sort_field", "value": "time", + "choice": []interface{}{ + map[string]interface{}{ + "name": "filename", "value": "filename", + }, + map[string]interface{}{ + "name": "line", "value": "line", + }, + map[string]interface{}{ + "name": "size", "value": "size", + }, + map[string]interface{}{ + "name": "time", "value": "time", + }, + }, + }, + map[string]interface{}{ + "type": "choice", "name": "sort_order", + "label": "sort_order", "value": "time", + "choice": []interface{}{ + map[string]interface{}{ + "name": "str", "value": "str", + }, + map[string]interface{}{ + "name": "str_r", "value": "str_r", + }, + map[string]interface{}{ + "name": "int", "value": "int", + }, + map[string]interface{}{ + "name": "int_r", "value": "int_r", + }, + map[string]interface{}{ + "name": "time", "value": "time", + }, + map[string]interface{}{ + "name": "time_r", "value": "time_r", + }, + }, + }, + }, + }, + map[string]interface{}{ + "template": "componet", "name": "web_site", "help": "web_site", + "context": "web", "command": "config", + "arguments": []interface{}{ + "web_site", + "format_field", "site", "%s", + }, + "display_result": "", + }, + map[string]interface{}{ + "template": "tail", "name": "tail", "help": "tail", + "context": "", "command": "", "arguments": []interface{}{}, + }, + }, + }, Help: "组件列表"}, }, Commands: map[string]*ctx.Command{ "client": &ctx.Command{Name: "client address [output [editor]]", Help: "添加浏览器配置, address: 默认地址, output: 输出路径, editor: 编辑器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { @@ -517,55 +695,248 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } } }}, - "/demo": &ctx.Command{Name: "/demo template", Help: "渲染模板, template: 模板名称", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Append("template", "index") - }}, - "template": &ctx.Command{Name: "template [file directory]|[name content]", Help: "添加模块, content: 模板内容, directory: 模板目录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "template": &ctx.Command{Name: "template [file [directory]]|[name [content]]", Help: "添加模板, content: 模板内容, directory: 模板目录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if web, ok := m.Target().Server.(*WEB); m.Assert(ok) { if len(arg) == 0 { - for _, v := range web.Template.Templates() { + for _, v := range web.template.Templates() { m.Add("append", "name", v.Name()) } m.Sort("name").Table() return } - if web.Template == nil { - web.Template = template.New("render").Funcs(ctx.CGI) + if web.template == nil { + web.template = template.New("render").Funcs(ctx.CGI) } dir := path.Join(m.Confx("template_dir", arg, 1), arg[0]) - if t, e := web.Template.ParseGlob(dir); e == nil { - web.Template = t + if t, e := web.template.ParseGlob(dir); e == nil { + web.template = t } else { + m.Log("info", "%s", e) if len(arg) > 1 { - web.Template = template.Must(web.Template.New(arg[0]).Parse(arg[1])) + web.template = template.Must(web.template.New(arg[0]).Parse(arg[1])) } else { - buf := bytes.NewBuffer(make([]byte, 1024)) - tmpl, e := web.Template.Clone() + tmpl, e := web.template.Clone() m.Assert(e) + tmpl.Funcs(ctx.CGI) + + buf := bytes.NewBuffer(make([]byte, 1024)) tmpl.ExecuteTemplate(buf, arg[0], m) m.Echo(string(buf.Bytes())) } } } }}, - "/render": &ctx.Command{Name: "/render template", Help: "渲染模板, template: 模板名称", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if web, ok := m.Target().Server.(*WEB); m.Assert(ok) { - w := m.Optionv("response").(http.ResponseWriter) - w.Header().Add("Content-Type", "text/html") - tmpl, e := web.Template.Clone() - m.Assert(e) - - for _, v := range m.Confv("template", arg[0]).([]interface{}) { - //执行命令 - val := v.(map[string]interface{}) - if _, ok := val["command"]; ok { - msg := m.Find(val["context"].(string)).Cmd(val["command"], val["argument"]) - msg.Option("title", val["title"]) - m.Assert(tmpl.ExecuteTemplate(w, val["name"].(string), msg)) + "componet": &ctx.Command{Name: "componet [group [order [arg...]]]", Help: "添加组件, group: 组件分组, arg...: 组件参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + switch len(arg) { + case 0: + for k, v := range m.Confv("componet").(map[string]interface{}) { + for i, val := range v.([]interface{}) { + value := val.(map[string]interface{}) + m.Add("append", "group", k) + m.Add("append", "order", i) + m.Add("append", "name", value["name"]) + m.Add("append", "help", value["help"]) + m.Add("append", "context", value["context"]) + m.Add("append", "command", value["command"]) } } + m.Sort("group").Table() + case 1: + for i, val := range m.Confv("componet", arg[0]).([]interface{}) { + value := val.(map[string]interface{}) + m.Add("append", "order", i) + m.Add("append", "name", value["name"]) + m.Add("append", "help", value["help"]) + m.Add("append", "context", value["context"]) + m.Add("append", "command", value["command"]) + } + m.Table() + case 2: + value := m.Confv("componet", []interface{}{arg[0], arg[1]}).(map[string]interface{}) + for k, v := range value { + m.Add("append", k, v) + } + m.Table() + default: + if com, ok := m.Confv("componet", []interface{}{arg[0], arg[1]}).(map[string]interface{}); ok { + for i := 2; i < len(arg)-1; i += 2 { + com[arg[i]] = arg[i+1] + } + } else { + m.Confv("componet", []interface{}{arg[0], arg[1]}, map[string]interface{}{ + "name": arg[2], "help": arg[3], + "context": m.Confx("componet_context", arg, 4), + "command": m.Confx("componet_command", arg, 5), + }) + break + } + } + }}, + "session": &ctx.Command{Name: "session", Help: "用户登录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + sessid := m.Option("sessid") + if sessid == "" && m.Options("username") && m.Options("password") { + sessid = m.Sess("aaa").Cmd("login", m.Option("username"), m.Option("password")).Result(0) + } + if sessid == "" && m.Options("remote_addr") { + sessid = m.Sess("aaa").Cmd("login", "ip", m.Option("remote_addr")).Result(0) + } + + login := m.Sess("aaa").Cmd("login", sessid).Sess("login", false) + m.Appendv("login", login) + m.Echo(sessid) + }}, + "/render": &ctx.Command{Name: "/render template", Help: "渲染模板, template: 模板名称", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if _, ok := m.Target().Server.(*WEB); m.Assert(ok) { + accept_json := strings.HasPrefix(m.Option("accept"), "application/json") + list := []interface{}{} + + // tmpl, e := web.template.Clone() + // m.Assert(e) + // tmpl.Funcs(ctx.CGI) + // + + tmpl := template.New("render").Funcs(ctx.CGI) + tmpl.ParseGlob("/Users/shaoying/context/usr/template/common/base.tmpl") + + w := m.Optionv("response").(http.ResponseWriter) + if accept_json { + w.Header().Add("Content-Type", "application/json") + } else { + w.Header().Add("Content-Type", "text/html") + } + + if m.Option("componet_group") == "" { + m.Option("componet_group", m.Conf("componet_group")) + } + group := m.Option("componet_group") + + right := false + if group == "login" { + right = true + } + + login := m + login = nil + + for count := 0; count == 0; { + order := -1 + if m.Option("componet_order") != "" { + order = m.Optioni("componet_order") + } + + if !right { + login = m.Spawn().Cmd("session").Appendv("login").(*ctx.Message) + } + if !right && login != nil { + if role := login.Confv("right", []interface{}{"right", "role"}); role != nil && role.(string) == "root" { + right = true + } + } + if !right && login != nil { + if role := login.Confv("right", []interface{}{group, "right", "role"}); role != nil && role.(string) == "owner" { + right = true + } + } + + for i, v := range m.Confv("componet", group).([]interface{}) { + if order != -1 && i != order { + continue + } + + val := v.(map[string]interface{}) + + order_right := right + if !order_right && login != nil { + if role := login.Confv("right", []interface{}{group, val["name"], "right", "role"}); role != nil && role.(string) == "share" { + order_right = true + } + } + if !order_right { + continue + } + + msg := m.Find(val["context"].(string)) + if msg == nil { + if !accept_json { + m.Assert(tmpl.ExecuteTemplate(w, val["template"].(string), m)) + } + continue + } + count++ + + msg.Option("componet_order", i) + + for k, v := range val { + if msg.Option(k) != "" { + continue + } + switch value := v.(type) { + case []string: + msg.Add("option", k, value) + case string: + msg.Add("option", k, value) + default: + msg.Put("option", k, value) + } + } + + args := []string{} + if val["arguments"] != nil { + for _, v := range val["arguments"].([]interface{}) { + switch value := v.(type) { + case string: + if len(value) > 1 && value[0] == '$' { + args = append(args, msg.Cap(value[1:])) + } else if len(value) > 1 && value[0] == '@' { + args = append(args, msg.Confx(value[1:])) + } else { + args = append(args, value) + } + } + } + } + if val["inputs"] != nil { + for _, v := range val["inputs"].([]interface{}) { + value := v.(map[string]interface{}) + if msg.Option(value["name"].(string)) == "" { + msg.Add("option", value["name"].(string), value["value"]) + } + } + } + + if msg.Cmd(val["command"], args); accept_json { + list = append(list, msg.Meta) + } else { + m.Assert(tmpl.ExecuteTemplate(w, val["template"].(string), msg)) + } + + if msg.Appends("sessid") { + http.SetCookie(w, &http.Cookie{Name: "sessid", Value: msg.Append("sessid")}) + m.Append("page_redirect", fmt.Sprintf("/render?componet_group=%s&componet_order=%s", + m.Option("componet_group", m.Option("last_componet_group")), + m.Option("componet_order", m.Option("last_componet_order")))) + return + } + } + + if count == 0 { + m.Option("last_componet_group", m.Option("componet_group")) + m.Option("last_componet_order", m.Option("componet_order")) + m.Option("componet_group", "login") + m.Option("componet_order", "-1") + group = m.Option("componet_group") + order = -1 + right = true + } + } + + if accept_json { + en := json.NewEncoder(w) + en.SetIndent("", " ") + en.Encode(list) + } } }}, }, diff --git a/usr/library/base.js b/usr/library/base.js index 6ab18a33..e4281724 100644 --- a/usr/library/base.js +++ b/usr/library/base.js @@ -1,59 +1,194 @@ - -function update(event, module, details, key) { - if (event) { - window[key+"timer"] = !window[key+"timer"]; - } - if (!window[key+"timer"]) { - return - } - console.log("update "+key) - setTimeout(function() { - action(event, module, details, key); - update(null, module, details, key); - }, refresh_time); +function insert_child(parent, element, html, position) { + var elm = document.createElement(element) + html && (elm.innerHTML = html) + return parent.insertBefore(elm, position || parent.firstElementChild) +} +function append_child(parent, element, html) { + var elm = document.createElement(element) + html && (elm.innerHTML = html) + parent.append(elm) + return elm +} +function insert_before(self, element, html) { + var elm = document.createElement(element) + html && (elm.innerHTML = html) + return self.parentElement.insertBefore(elm, self) } -function input(event, module, details, key) { - if (event.code == "Enter") { - action(event, module, details, key); - } +function copy_to_clipboard(text) { + var clipboard = document.querySelector("#clipboard") + clipboard.value = text + clipboard.select() + document.execCommand("copy") + clipboard.blur() + + var clipstack = document.querySelector("#clipstack") + insert_child(clipstack, "option").value = clipboard.value + clipstack.childElementCount > 3 && clipstack.removeChild(clipstack.lastElementChild) } -function action(event, module, details, key) { - var input = document.getElementsByClassName(key+"_input"); - for (var i = 0; i < input.length; i++ ){ - if (input[i].value != "") { - details.push(input[i].value) - } - } - ctx.POST("", {module:module, details:details}, function(msg) { - if (msg && msg.result) { - var result = document.getElementsByClassName(key+"_result")[0]; - result.innerHTML = msg.result; - } - if (!msg || !msg.append || msg.append.length < 1) { - return - } +function send_command(form, cb) { + var data = {} + for (var key in form.dataset) { + data[key] = form.dataset[key] + } + for (var i = 0; i < form.length; i++) { + data[form[i].name] = form[i].value + } - var append = document.getElementsByClassName(key+"_append")[0]; - if (append.rows.length == msg[msg.append[0]].length+1) { - return - } - append.innerHTML = ''; - var tr = append.insertRow(0); - for (var i in msg.append) { - var th = tr.appendChild(document.createElement("th")); - th.appendChild(document.createTextNode(msg.append[i])); - } + context.GET("", data, function(msg) { + msg = msg[0] - for (var i = 0; i < msg[msg.append[0]].length; i++) { - var tr = append.insertRow(1); - for (var j in msg.append) { - var td = tr.appendChild(document.createElement("td")); - td.appendChild(document.createTextNode(msg[msg.append[j]][i])); - } - } - var div = append.parent; + var result = document.querySelector("code.result."+data["componet_name"]+" pre") + result && (result.innerHTML = (msg.result || []).join("")) - }) - return false; + var append = document.querySelector("table.append."+data["componet_name"]) + append && (append.innerHTML = "") + + if (append && msg.append) { + var tr = append_child(append, "tr") + for (var i in msg.append) { + append_child(tr, "th", msg.append[i]) + } + + var ncol = msg.append.length + var nrow = msg[msg.append[0]].length + for (var i = 0; i < nrow; i ++) { + var tr = append_child(append, "tr") + for (var k in msg.append) { + append_child(tr, "td", msg[msg.append[k]][i]) + } + } + } + + typeof(cb) == "function" && cb(msg) + }) +} +function onaction(event, action) { + switch (action) { + case "command": + send_command(event.target.form) + break + case "input": + switch (event.key) { + case "Enter": + var form = event.target.form + for (var i = 0; i < form.length; i++) { + if (form[i] == event.target) { + continue + } + (i == form.length-1)? send_command(form): form[i+1].focus() + } + break + case "Escape": + event.target.value = "" + event.target.blur() + break + } + break + case "keymap": + switch (event.key) { + case "g": + document.querySelectorAll("form.option label.keymap").forEach(function(item) { + item.className = (item.className == "keymap show")? "keymap hide": "keymap show" + }) + break + default: + if (inputs[event.key]) { + inputs[event.key].focus() + } + break + } + break + case "copy": + copy_to_clipboard(event.target.innerText) + break + } +} +var inputs = {} +var ninput = 0 +var keymap = ['a', 'b', 'c'] +function init_option() { + inputs = {} + ninput = 0 + keymap =[] + for (var i = 97; i < 123; i++) { + if (i == 103) { + continue + } + keymap.push(String.fromCharCode(i)) + } + + document.querySelectorAll("form.option input").forEach(function(input) { + if (ninput < keymap.length && input.style.display != "none") { + input.title = "keymap: "+keymap[ninput] + input.dataset["keymap"] = keymap[ninput] + insert_before(input, "label", "("+keymap[ninput]+")").className = "keymap" + inputs[keymap[ninput++]] = input + } + }) +} +function init_append(event) { + var append = document.querySelectorAll("table.append").forEach(function(item) { + item.onclick = function(event) { + if (event.target.tagName == "TD") { + copy_to_clipboard(event.target.innerText) + } + } + }) +} +function init_result(event) { + var result = document.querySelectorAll("code.result pre").forEach(function(item) { + item.onclick = function(event) { + copy_to_clipboard(event.target.innerText) + } + }) +} +function init_download(event) { + var option = document.querySelector("form.option.dir") + if (!option) { + return + } + option["dir"].value && send_command(option) + + var append = document.querySelector("table.append.dir") + append.onclick = function(event) { + if (event.target.tagName == "A") { + if (event.target.dataset.type != "true") { + location.href = option["dir"].value+"/"+event.target.innerText + return + } + + option["dir"].value = option["dir"].value+"/"+event.target.innerText + send_command(option, function(msg) { + option["dir"].value = msg.dir.join("") + }) + } else if (event.target.tagName == "TD") { + copy_to_clipboard(event.target.innerText) + } else if (event.target.tagName == "TH") { + option["sort_field"].value = event.target.innerText + + var sort_order = option["sort_order"] + switch (event.target.innerText) { + case "filename": + sort_order.value = (sort_order.value == "str")? "str_r": "str" + break + case "line": + case "size": + sort_order.value = (sort_order.value == "int")? "int_r": "int" + break + case "time": + sort_order.value = (sort_order.value == "time")? "time_r": "time" + break + } + + send_command(option) + } + } +} + +window.onload = function() { + init_option() + init_append() + init_result() + init_download() } diff --git a/usr/library/context.js b/usr/library/context.js index d53f55e8..3c2de56c 100644 --- a/usr/library/context.js +++ b/usr/library/context.js @@ -1,202 +1,47 @@ -ctx = { - Cookie: function(key, value) {//{{{ - if (value == undefined) { - var pattern = new RegExp(key+"=([^;]*);?"); - var result = pattern.exec(document.cookie); - if (result && result.length > 0) { - return result[1]; - } - return ""; - } +context = { + GET: function(url, form, cb) { + form = form || {} - document.cookie = key+"="+value; - return this.Cookie(key); - },//}}} - Search: function(key, value) {//{{{ - var args = {}; - var search = location.search.split("?"); - if (search.length > 1) { - var searchs = search[1].split("&"); - for (var i = 0; i < searchs.length; i++) { - var keys = searchs[i].split("="); - args[keys[0]] = decodeURIComponent(keys[1]); - } - } - - if (typeof key == "object") { - for (var k in key) { - if (key[k] != undefined) { - args[k] = key[k]; - } - } - } else if (value == undefined) { - return args[key] || ""; - } else { - args[key] = value; - } - - var arg = []; - for (var k in args) { - arg.push(k+"="+encodeURIComponent(args[k])); - } - location.search = arg.join("&"); - },//}}} - GET: function(url, form, cb) {//{{{ - var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function() { - switch (xhr.readyState) { - case 4: - switch (xhr.status) { - case 200: - try { - var msg = JSON.parse(xhr.responseText||'{"result":[]}'); - } catch (e) { - msg = {"result": [xhr.responseText]} - } - - msg && console.log(msg) - msg.result && console.log(msg.result.join("")); - typeof cb == "function" && cb(msg) - } - break; - } - } - - form = form || {} - form["dir"] = form["dir"] || this.Search("dir") || undefined - form["module"] = form["module"] || this.Search("module") || undefined - form["domain"] = form["domain"] || this.Search("domain") || undefined - - var args = []; - for (k in form) { - if (form[k] instanceof Array) { - for (i in form[k]) { - args.push(k+"="+encodeURIComponent(form[k][i])); - } - } else if (form[k] != undefined) { - args.push(k+"="+encodeURIComponent(form[k])); - } - } - - var arg = args.join("&"); - if (arg) { - url += "?"+arg + var args = []; + for (var k in form) { + if (form[k] instanceof Array) { + for (i in form[k]) { + args.push(k+"="+encodeURIComponent(form[k][i])); + } + } else if (form[k] != undefined) { + args.push(k+"="+encodeURIComponent(form[k])); + } } - xhr.open("GET", url); - console.log("GET: "+url+"?"+arg); - xhr.send(); - },//}}} - POST: function(url, form, cb) {//{{{ - var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function() { - switch (xhr.readyState) { - case 4: - switch (xhr.status) { - case 200: - try { - var msg = JSON.parse(xhr.responseText||'{"result":[]}'); - } catch (e) { - msg = {"result": [xhr.responseText]} - } + var arg = args.join("&"); + arg && (url += ((url.indexOf("?")>-1)? "&": "?") + arg) + console.log("GET: "+url); - msg && console.log(msg) - msg.result && console.log(msg.result.join("")); - typeof cb == "function" && cb(msg) - } - break; - } - } + var xhr = new XMLHttpRequest(); + xhr.open("GET", url); + xhr.setRequestHeader("Accept", "application/json") - xhr.open("POST", url); - xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + xhr.onreadystatechange = function() { + if (xhr.readyState != 4) { + return + } + if (xhr.status != 200) { + return + } + try { + var msg = JSON.parse(xhr.responseText||'{"result":[]}'); + } catch (e) { + var msg = {"result": [xhr.responseText]} + } - form = form || {} - form["dir"] = form["dir"] || this.Search("dir") || undefined - form["module"] = form["module"] || this.Search("module") || undefined - form["domain"] = form["domain"] || this.Search("domain") || undefined - - var args = []; - for (k in form) { - if (form[k] instanceof Array) { - for (i in form[k]) { - args.push(k+"="+encodeURIComponent(form[k][i])); - } - } else if (form[k] != undefined) { - args.push(k+"="+encodeURIComponent(form[k])); - } - } - - var arg = args.join("&"); - console.log("POST: "+url+"?"+arg); - xhr.send(arg); - },//}}} - Refresh: function() {//{{{ - location.assign(location.href); - },//}}} - - Cap: function(cap, cb) {//{{{ - if (typeof cap == "function") { - cb = cap; - cap = undefined; - } - - var args = {ccc:"cache"}; - if (cap != undefined) { - args.name = cap; - } - - this.POST("", args, function(msg) { - var value = msg.result.join(""); - typeof cb == "function" && cb(value); - }); - },//}}} - Conf: function(name, value, cb) {//{{{ - if (typeof name == "function") { - value = name; - name = undefined; - } - if (typeof value == "function") { - cb = value; - value = undefined; - } - - var args = {ccc:"config"}; - if (name != undefined) { - args.name = name - } - if (value != undefined) { - args.value = value - } - - this.POST("", args, function(msg) { - var value = msg.result.join(""); - typeof cb == "function" && cb(value); - }); - },//}}} - Cmd: function(cmd, value, cb) {//{{{ - if (typeof cmd == "function") { - value = cmd; - cmd = undefined; - } - if (typeof value == "function") { - cb = value; - value = undefined; - } - - var args = {ccc:"command"}; - if (cmd != undefined) { - args.name = cmd - } - if (value != undefined) { - args.value = JSON.stringify(value) - } - - this.POST("", args, cb); - },//}}} - Module: function(module, domain) {//{{{ - this.Search({module:module, domain:domain}) - },//}}} -}; - + console.log(msg) + msg.result && console.log(msg.result.join("")); + if (msg.page_redirect) { + location.href = msg.page_redirect.join("") + } + typeof cb == "function" && cb(msg) + } + xhr.send(); + }, +} diff --git a/usr/library/wiki.js b/usr/library/wiki.js deleted file mode 100644 index 8d4eb8a9..00000000 --- a/usr/library/wiki.js +++ /dev/null @@ -1,211 +0,0 @@ -function jumpto(url) { - if (url == "..") { - var ps = locaiton.href.split(); - } - location.href=url; -} - -function keyup(event) { - console.log(event); - if (typeof window.control == "function") { - control(event); - } - if (event.key == "z") { - var input = document.getElementsByClassName("query_input")[0]; - if (!window.query_show) { - window.query_show = true; - var query = document.getElementsByClassName("query_menu")[0]; - var input = query.getElementsByTagName("input")[0]; - input.style.visibility = "visible"; - input.style.width = "80px"; - input.focus(); - } - return true - } - return true -} - -document.onkeyup = keyup; -function toggle(side) { - if (side == "left") { - window.left_list_hide = !window.left_list_hide; - var list = document.getElementsByClassName("list")[0]; - var content = document.getElementsByClassName("content")[0]; - if (left_list_hide) { - list.style.visibility = "hidden"; - list.style.width="0px"; - list.style.height="0px"; - list.style["min-width"]="0px"; - content.style.width="100%"; - } else { - list.style.visibility = "visible"; - list.style.width="15%"; - list.style.height="100%"; - list.style["min-width"]="180px"; - content.style.width="85%"; - } - } -} - -function menu() { - var max = 0; - var min = 1000; - var list = []; - var hs = ["h2", "h3", "h4"]; - for (var i = 0; i < hs.length; i++) { - var head = document.getElementsByTagName(hs[i]); - for (var j = 0; j < head.length; j++) { - head[j].id = "head"+head[j].offsetTop; - head[j].onclick = function(event) {} - list.push({"level": hs[i], "position": head[j].offsetTop, "title": head[j].innerText, "hash": head[j].id}) - if (head[j].offsetTop > max) { - max = head[j].offsetTop; - } - if (head[j].offsetTop < min) { - min = head[j].offsetTop; - } - } - } - max = max - min; - - var link = []; - var a = document.getElementsByTagName("a"); - for (var i = 0; i < a.length; i++) { - link.push({href: a[i].href, title: a[i].innerText}); - } - - for (var i = 0; i < list.length-1; i++) { - for (var j = i+1; j < list.length; j++) { - if (list[j].position < list[i].position) { - var a = list[i]; - list[i] = list[j]; - list[j] = a; - } - } - } - - var index = [-1, 0, 0] - for (var i = 0; i < list.length; i++) { - if (list[i].level == "h2") { - index[0]++; - index[1]=0; - index[2]=0; - } else if (list[i].level == "h3") { - index[1]++; - index[2]=0; - } else { - index[2]++; - } - - list[i].index4 = index[2]; - list[i].index3 = index[1]; - list[i].index2 = index[0]; - } - - var m = document.getElementsByClassName("menu"); - for (var i = 0; i < m.length; i++) { - for (var j = 0; j < list.length; j++) { - var text = list[j].index2+"." - if (list[j].level == "h3") { - text += list[j].index3 - } else if (list[j].level == "h4") { - text += list[j].index3+"."+list[j].index4 - } - - text += " " - text += list[j].title; - - var h = document.getElementById(list[j].hash) - h.innerText = text - - var one = m[i].appendChild(document.createElement("div")); - var a = one.appendChild(document.createElement("a")); - a.href = "#"+list[j].hash; - a.innerText = text+" ("+parseInt((list[j].position-min)/max*100)+"%)"; - - one.className = list[j].level; - } - } - - var m = document.getElementsByClassName("link"); - for (var i = 0; i < m.length; i++) { - var one = m[i].appendChild(document.createElement("div")); - var a = one.appendChild(document.createTextNode("相关链接: ")); - - for (var j = 0; j < link.length; j++) { - var one = m[i].appendChild(document.createElement("div")); - var a = one.appendChild(document.createTextNode(link[j].title+": ")); - var a = one.appendChild(document.createElement("a")); - a.href = link[j].href - a.innerText = a.href - } - } - - var m = document.getElementsByTagName("pre"); - for (var i = 0; i < m.length; i++) { - var line = (m[i].clientHeight-10)/15 - // if (line < 3) { - // continue - // } - console.log(m[i].clientHeight) - var nu = m[i].parentElement.insertBefore(document.createElement("div"), m[i]); - nu.className = "number1" - - for (var j = 1; j <= line; j++) { - console.log(j) - var li = nu.appendChild(document.createElement("div")); - li.appendChild(document.createTextNode(""+j)); - } - } -} - -function query(event) { - if (event) { - if (event.code == "Enter") { - jumpto("/wiki/?query="+encodeURIComponent(event.target.value)); - } - console.log("what") - return true - } - window.query_show = !window.query_show; - var query = document.getElementsByClassName("query_menu")[0]; - var input = query.getElementsByTagName("input")[0]; - if (window.query_show) { - input.style.visibility = "visible"; - input.style.width = "80px"; - - } else { - input.style.visibility = "hidden"; - input.style.width = "0px"; - } -} - -var tags_list = {}; -ctx.GET("/wiki/define.json", undefined, function(msg){ - tags_list = msg["define"]; -}) - -function tags(event) { - console.log(event); - - if (event.srcElement.tagName == "CODE") { - var tag = document.getSelection().toString(); - console.log(tag); - if (tag && tag.length > 0 && tags_list[tag]) { - var position = tags_list[tag].position; - if (position.length == 1) { - jumpto("/wiki/src/"+position[0].file+"#hash_"+position[0].line); - } else { - jumpto("/wiki/?query="+encodeURIComponent(tag)); - } - } - } -} - -document.onmouseup = tags; -window.onload = function() { - toggle(); - if (location.href.endsWith(".md")) { - menu(); - } -} diff --git a/usr/template/common/base.html b/usr/template/common/base.html deleted file mode 100644 index d14b78a9..00000000 --- a/usr/template/common/base.html +++ /dev/null @@ -1,145 +0,0 @@ -{{define "head"}} - - - - -{{option .Meta "page_title"}} - - - - - -{{end}} - -{{define "code"}} -
{{.}}
-{{end}} - -{{define "notice"}} -
[notice] - {{template "code" result .Meta}} -
- -{{end}} - -{{define "detail"}} -{{$msg := .}} -{{$key := append . "title"|meta}} -
{{option . "title"}} - {{range option . "ninput"|meta|list}} - - {{end}} - {{if option . "refresh"}} - - - {{end}} -
-
-
-
-
- -{{end}} - -{{define "result"}} -
{{option . "title"}} - {{template "code" result .Meta|unscaped}} -
-{{end}} - -{{define "append_link"}} -{{.}} - -{{end}} - -{{define "append"}} -
{{option . "title"}} - - {{$msg := .}} - {{$ncol := append . |len}} - {{$nrow := append . 0|append .|len}} - {{range append .}}{{end}} - {{range $row, $val := append . 0|append .}} - - {{range append $msg}} - {{$value := append $msg . $row}} - - {{end}} - - {{end}} -
{{.}}
- {{if eq . "filename"}} - {{template "append_link" $value}} - {{else}} - {{$value}} - {{end}} -
-
- -{{end}} - -{{define "main"}} -welcome to context world! -{{end}} - -{{define "tail"}} - -{{end}} diff --git a/usr/template/common/base.tmpl b/usr/template/common/base.tmpl new file mode 100644 index 00000000..a6771bc7 --- /dev/null +++ b/usr/template/common/base.tmpl @@ -0,0 +1,138 @@ +{{define "head"}} + + + + +{{option .Meta "page_title"}} + + + + + +{{end}} + +{{define "detail"}}{{detail .}}{{end}} +{{define "option"}}{{option .}}{{end}} +{{define "append"}}{{append .}}{{end}} +{{define "result"}}{{result .}}{{end}} + +{{define "clipboard"}} +
clipboard + + +
+{{end}} + +{{define "componet"}} +
{{option .Meta "context"}}.{{option .Meta "command"}} +
+ + {{range $index, $input := option . "inputs"}} +
+ {{$type := index $input "type"}} + {{if eq $type "button"}} + + {{else if eq $type "choice"}} + {{$default_value := index $input "value"}} + + + {{else}} + + + {{end}} +
+ {{end}} +
+
+ + {{if index .Meta "display_append"}} + {{option .Meta "display_append"}} + {{else}} + + {{$msg := .}} + {{range $field := append .}}{{end}} + {{range $line := table .}} + {{range $field := append $msg}}{{end}} + {{end}} +
{{$field}}
{{index $line $field|unescape}}
+ {{end}} + + {{if index .Meta "display_result"}} + {{option .Meta "display_result"}} + {{else}} +
{{result .Meta}}
+ {{end}} +
+{{end}} + +{{define "tail"}} + + + +{{end}} diff --git a/usr/template/common/login.html b/usr/template/common/login.html deleted file mode 100644 index 472887a7..00000000 --- a/usr/template/common/login.html +++ /dev/null @@ -1,94 +0,0 @@ -{{define "login"}} -
login -
- - - -
-
-{{end}} - -{{define "userinfo"}} -
userinfo - welcome {{option . "username"}} to context world - -
- - -{{end}} - -{{define "share"}} -
share - - {{$msg := .}} - {{$ncol := append . |len}} - {{$nrow := append . 0|append .|len}} - {{range append .}}{{end}} - {{range $row, $val := append . 0|append .}} - - {{range append $msg}} - {{$value := append $msg . $row}} - - {{end}} - - {{end}} -
{{.}}
- {{if eq . "to"}} - {{if eq $value ""}} - - {{else}} - {{$value}} - {{end}} - {{else if eq . "value"}} - {{$value}} - {{else}} - {{$value}} - {{end}} -
-
- -{{end}} - -{{$msg := .}} -{{$meta := .Meta}} - -{{template "head" $meta}} -{{if meta $meta.notice}} - {{template "notice" $meta}} -{{end}} -{{template "login" $meta}} -{{template "tail" $meta}} diff --git a/usr/template/common/main.html b/usr/template/common/main.html deleted file mode 100644 index ce3e2dc1..00000000 --- a/usr/template/common/main.html +++ /dev/null @@ -1,9 +0,0 @@ -{{$msg := .}} -{{$meta := .Meta}} - -{{template "head" $meta}} -{{if meta $meta.message}} - {{template "message" $meta}} -{{end}} -{{template "main" $msg}} -{{template "tail" $meta}} diff --git a/usr/template/common/wiki.html b/usr/template/common/wiki.html deleted file mode 100644 index 835fe9ab..00000000 --- a/usr/template/common/wiki.html +++ /dev/null @@ -1,222 +0,0 @@ -{{define "wiki_head"}} -{{end}} - -{{define "wiki_menu"}} -{{end}} - -{{define "wiki_list"}} - -
-
-
-
- -
Q
-
-
shylinux
-
-
- {{$msg := .}} - {{$ncol := append . |len}} - {{$nrow := append . 0|append .|len}} -
    -
  • -
    返回上一层
    -
  • - {{range $row, $val := append . 0|append .}} -
  • -
    - {{append $msg "name" $row}} -
    -
  • - {{end}} -
-
-{{end}} - -{{define "wiki_body"}} - -
-
-
- {{if option . "modify_time"|meta}} -
上次修订时间: {{option . "modify_time"|meta}} 修订次数: {{option . "modify_count"|meta}}
- {{end}} -
上次阅读时间: {{option . "last_record_time"|meta}} 总访问量: {{option . "record_count"|meta}}
-
- - -
- {{range option . "nline"|meta|list}} -
{{.}}
- {{end}} -
- {{$msg := .}} - {{if append . "name"}} - {{$l := append . "name"|len}} - {{if eq $l 1}} - - {{else}} -
    - {{range $i, $v := append . "name"}} - - {{end}} -
      - {{end}} - {{else if append . "code"|meta}} -

      {{append . "code"|meta}}

      - {{else}} -

      {{append . "body"|meta|unscaped}}

      - {{end}} -
-
- -
- -{{end}} diff --git a/usr/template/travel.html b/usr/template/travel.html deleted file mode 100644 index b66bb94d..00000000 --- a/usr/template/travel.html +++ /dev/null @@ -1,431 +0,0 @@ -{{define "head"}} - - - - - - -{{end}} - -{{define "cache"}} -{{$meta := .}} -
cache - - {{range .append}}{{end}} - {{range .append}}{{end}} - {{$l := index .append|len}} - {{if gt $l 0}} - {{$first := index .append 0}} - {{range $i, $k := index . $first}} - - {{range $key := index $meta "append"}} - {{$content := index $meta $key $i}} - - {{end}} - - {{end}} - {{end}} -
{{.}}
- {{$content}} -
-
- -{{end}} - -{{define "config"}} -
config - - {{range .append}}{{end}} - {{range .append}}{{end}} - {{$l := index .append|len}} - {{if gt $l 0}} - {{$meta := .}} {{$first := index .append 0}} - {{range $i, $k := index . $first}} - {{$config := index $meta "key" $i}} - {{range $key := index $meta "append"}} - {{if eq $key "value"}} - - {{else}} - - {{end}} - {{end}} - - {{end}} - {{end}} -
{{.}}
- - - {{index $meta $key $i}} -
-
- -{{end}} - -{{define "command2"}} -{{$meta := .}} -
command -
- {{$l := index .append|len}} - {{if gt $l 0}} - {{$first := index .append 0}} - {{range $i, $k := index . $first}} - {{$command := index $meta "key" $i}} -
-
- - {{$command}}: {{index $meta "help" $i}}
- {{index $meta "name" $i}} -
-
-
- - -
- - -
- {{end}} - {{end}} -
-
-
-
-
- -{{end}} - -{{define "command"}} -
command - - {{range .append}}{{end}} - {{range .append}}{{end}} - {{$l := index .append|len}} - {{if gt $l 0}} - {{$meta := .}} {{$first := index .append 0}} - {{range $i, $k := index . $first}} - {{$command := index $meta "key" $i}} - {{range $key := index $meta "append"}} - - {{end}} - - {{end}} - {{end}} -
{{.}}
- {{if eq $key "input"}} - - {{else if eq $key "key"}} - {{index $meta $key $i}} - {{else}} - {{index $meta $key $i}} - {{end}} -
-
-
-
-
-
- -{{end}} - -{{define "module"}} -
- - {{range .append}}{{end}} - {{range .append}}{{end}} - {{$l := index .append|len}} - {{if gt $l 0}} - {{$meta := .}} {{$first := index .append 0}} - {{range $i, $k := index . $first}} - - {{range $key := index $meta "append"}} - {{if eq $key "name"}} - - {{else}} - - {{end}} - {{end}} - - {{end}} - {{end}} -
{{.}}
- {{index $meta $key $i}} - - {{index $meta $key $i}} -
-
-{{end}} - -{{define "domain"}} -
- - {{range .append}}{{end}} - {{range .append}}{{end}} - {{$l := index .append|len}} - {{if gt $l 0}} - {{$meta := .}} {{$first := index .append 0}} - {{range $i, $k := index . $first}} - - {{range $key := index $meta "append"}} - {{if eq $key "name"}} - - {{else}} - - {{end}} - {{end}} - - {{end}} - {{end}} -
{{.}}
- {{index $meta $key $i}} - - {{index $meta $key $i}} -
-
-{{end}} - -{{define "tail"}} - - - -{{end}} - -{{define "main"}} -{{$msg := .}} -{{$meta := .Meta}} -{{$sess := $msg.Sessions}} -{{range .Meta.tmpl}} - {{if eq . "login"}} - {{template "login" $meta}} - {{else if eq . "userinfo"}} - {{template "userinfo" $msg}} - {{else if eq . "share"}} - {{template "share" $sess.share}} - {{else if eq . "cache"}} - {{template "cache" $sess.cache.Meta}} - {{else if eq . "config"}} - {{template "config" $sess.config.Meta}} - {{else if eq . "command"}} - {{template "command" $sess.command.Meta}} - {{template "command2" $sess.command.Meta}} - {{else if eq . "module"}} - {{template "module" $sess.module.Meta}} - {{else if eq . "domain"}} - {{template "domain" $sess.domain.Meta}} - {{end}} -{{end}} -{{end}} diff --git a/usr/template/upload.html b/usr/template/upload.html deleted file mode 100644 index cc19746e..00000000 --- a/usr/template/upload.html +++ /dev/null @@ -1,163 +0,0 @@ -{{define "list"}} -
- - {{range .append}}{{end}} - - - {{$sort := meta .sort}} - {{$reverse := meta .reverse}} - {{range .append}} - {{if eq $sort .}} - - {{else if eq $reverse .}} - - {{else if eq . "path"}} - {{else}} - - {{end}} - {{end}} - - - {{if .append}} - {{$meta := .}} - {{$first := index .append 0}} - {{range $i, $k := index . $first}} - - {{range $key := index $meta "append"}} - {{if eq $key "name"}} - {{$type := index $meta "type" $i}} - - {{else if eq $key "path"}} - {{else}} - - {{end}} - {{end}} - - {{end}} - {{end}} -
{{.}}{{.}}{{.}}
- {{index $meta $key $i}} - - {{index $meta $key $i}} -
-
- - -{{end}} - -{{define "git"}} -
branch -
{{index . "result"}}
-
-
status -
{{index . "result"}}
-
-{{end}} - -{{define "tmux"}} -{{$meta := .}} -{{range $index, $value := index $meta "append"}} -
{{$value}} - {{if eq $value "buffer"}} - - - - - {{else}} -
{{meta $meta $value}}
- {{end}} -
-{{end}} -{{end}} - -{{define "upload"}} -
upload -
- -
-
-{{end}} - -{{define "create"}} -
create -
- - - -
filename:
content:
-
-
-{{end}} - -{{define "main"}} -{{$msg := .}} -{{$meta := .Meta}} -{{$sess := .Sessions}} -{{range .Meta.tmpl}} - {{$tmpl := index $sess .}} - - {{if eq . "login"}} - {{template "login" $meta}} - {{else if eq . "userinfo"}} - {{template "userinfo" $msg}} - {{else if eq . "share"}} - {{template "share" $sess.share}} - {{else if eq . "list"}} - {{template "list" $msg.Sessions.list.Meta}} - {{else if eq . "tmux"}} - {{template "tmux" $msg.Sessions.tmux.Meta}} - {{else if eq . "git"}} - {{if $msg.Sessions.git}} - {{template "git" $msg.Sessions.git.Meta}} - {{end}} - {{else if eq . "upload"}} - {{template "upload" $msg}} - {{else if eq . "create"}} - {{template "create" $msg}} - {{else}} - {{end}} -{{end}} -{{end}} -