mirror of
https://shylinux.com/x/ContextOS
synced 2025-04-26 17:24:05 +08:00
mac add code & wiki
This commit is contained in:
parent
880551e252
commit
32d272ee42
@ -244,9 +244,20 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
|||||||
|
|
||||||
args := []string{}
|
args := []string{}
|
||||||
rest := []string{}
|
rest := []string{}
|
||||||
|
exec := true
|
||||||
|
execexec := false
|
||||||
exports := []map[string]string{}
|
exports := []map[string]string{}
|
||||||
for i := 0; i < len(detail); i++ {
|
for i := 0; i < len(detail); i++ {
|
||||||
switch detail[i] {
|
switch detail[i] {
|
||||||
|
case "?":
|
||||||
|
if !ctx.Right(detail[i+1]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
case "??":
|
||||||
|
exec = false
|
||||||
|
execexec = execexec || ctx.Right(detail[i+1])
|
||||||
|
i++
|
||||||
case "<":
|
case "<":
|
||||||
pipe := m.Spawn().Cmd("import", detail[i+1])
|
pipe := m.Spawn().Cmd("import", detail[i+1])
|
||||||
msg.Copy(pipe, "append")
|
msg.Copy(pipe, "append")
|
||||||
@ -254,12 +265,36 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
|||||||
case ">":
|
case ">":
|
||||||
exports = append(exports, map[string]string{"file": detail[i+1]})
|
exports = append(exports, map[string]string{"file": detail[i+1]})
|
||||||
i++
|
i++
|
||||||
|
case ">$":
|
||||||
|
if i == len(detail)-2 {
|
||||||
|
exports = append(exports, map[string]string{"cache": detail[i+1], "index": "result"})
|
||||||
|
i += 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
exports = append(exports, map[string]string{"cache": detail[i+1], "index": detail[i+2]})
|
||||||
|
i += 2
|
||||||
|
case ">@":
|
||||||
|
if i == len(detail)-2 {
|
||||||
|
exports = append(exports, map[string]string{"config": detail[i+1], "index": "result"})
|
||||||
|
i += 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
exports = append(exports, map[string]string{"config": detail[i+1], "index": detail[i+2]})
|
||||||
|
i += 2
|
||||||
case "|":
|
case "|":
|
||||||
detail, rest = detail[:i], detail[i+1:]
|
detail, rest = detail[:i], detail[i+1:]
|
||||||
|
case "%":
|
||||||
|
rest = append(rest, "select")
|
||||||
|
detail, rest = detail[:i], append(rest, detail[i+1:]...)
|
||||||
default:
|
default:
|
||||||
args = append(args, detail[i])
|
args = append(args, detail[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !exec && !execexec {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
detail = args
|
detail = args
|
||||||
|
|
||||||
if msg.Cmd(detail); msg.Hand {
|
if msg.Cmd(detail); msg.Hand {
|
||||||
@ -270,8 +305,25 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range exports {
|
for _, v := range exports {
|
||||||
|
m.Log("info", "export %v", v)
|
||||||
|
if v["file"] != "" {
|
||||||
m.Spawn().Copy(msg, "option").Copy(msg, "append").Copy(msg, "result").Cmd("export", v["file"])
|
m.Spawn().Copy(msg, "option").Copy(msg, "append").Copy(msg, "result").Cmd("export", v["file"])
|
||||||
}
|
}
|
||||||
|
if v["cache"] != "" {
|
||||||
|
if v["index"] == "result" {
|
||||||
|
m.Cap(v["cache"], strings.Join(msg.Meta["result"], ""))
|
||||||
|
} else {
|
||||||
|
m.Cap(v["cache"], msg.Append(v["index"]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v["config"] != "" {
|
||||||
|
if v["index"] == "result" {
|
||||||
|
m.Conf(v["config"], strings.Join(msg.Meta["result"], ""))
|
||||||
|
} else {
|
||||||
|
m.Conf(v["config"], msg.Append(v["index"]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(rest) > 0 {
|
if len(rest) > 0 {
|
||||||
pipe := m.Spawn().Copy(msg, "option").Copy(msg, "append").Cmd("cmd", rest)
|
pipe := m.Spawn().Copy(msg, "option").Copy(msg, "append").Cmd("cmd", rest)
|
||||||
@ -298,7 +350,12 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
|||||||
case "$":
|
case "$":
|
||||||
m.Echo(msg.Cap(arg[1]))
|
m.Echo(msg.Cap(arg[1]))
|
||||||
case "@":
|
case "@":
|
||||||
m.Echo(msg.Conf(arg[1]))
|
value := msg.Option(arg[1])
|
||||||
|
if value == "" {
|
||||||
|
value = msg.Conf(arg[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Echo(value)
|
||||||
default:
|
default:
|
||||||
m.Echo(arg[0]).Echo(arg[1])
|
m.Echo(arg[0]).Echo(arg[1])
|
||||||
}
|
}
|
||||||
@ -551,7 +608,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
|||||||
yac.Cmd("train", "stm", "echo", "echo", "rep{", "exp", "}")
|
yac.Cmd("train", "stm", "echo", "echo", "rep{", "exp", "}")
|
||||||
yac.Cmd("train", "stm", "return", "return", "rep{", "exp", "}")
|
yac.Cmd("train", "stm", "return", "return", "rep{", "exp", "}")
|
||||||
|
|
||||||
yac.Cmd("train", "word", "word", "mul{", "~", "!", "=", "\\|", "\\<", "\\>", "exe", "str", "[a-zA-Z0-9_/\\-.:]+", "}")
|
yac.Cmd("train", "word", "word", "mul{", "~", "!", "=", "\\?\\?", "\\?", "<", ">$", ">@", ">", "\\|", "%", "exe", "str", "[a-zA-Z0-9_/\\-.:]+", "}")
|
||||||
yac.Cmd("train", "cmd", "cmd", "rep{", "word", "}")
|
yac.Cmd("train", "cmd", "cmd", "rep{", "word", "}")
|
||||||
yac.Cmd("train", "exe", "exe", "$", "(", "cmd", ")")
|
yac.Cmd("train", "exe", "exe", "$", "(", "cmd", ")")
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -27,9 +27,10 @@ type MUX interface {
|
|||||||
}
|
}
|
||||||
type WEB struct {
|
type WEB struct {
|
||||||
*http.Client
|
*http.Client
|
||||||
|
|
||||||
|
*http.Server
|
||||||
*http.ServeMux
|
*http.ServeMux
|
||||||
server *http.Server
|
*template.Template
|
||||||
template *template.Template
|
|
||||||
|
|
||||||
*ctx.Context
|
*ctx.Context
|
||||||
}
|
}
|
||||||
@ -173,16 +174,24 @@ func (web *WEB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
|
|||||||
func (web *WEB) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
func (web *WEB) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
||||||
web.Configs["root_index"] = &ctx.Config{Name: "root_index", Value: "/render", Help: "默认路由"}
|
web.Configs["root_index"] = &ctx.Config{Name: "root_index", Value: "/render", Help: "默认路由"}
|
||||||
web.Configs["logheaders"] = &ctx.Config{Name: "logheaders(yes/no)", Value: "no", Help: "日志输出报文头"}
|
web.Configs["logheaders"] = &ctx.Config{Name: "logheaders(yes/no)", Value: "no", Help: "日志输出报文头"}
|
||||||
|
web.Configs["template_sub"] = &ctx.Config{Name: "template_sub", Value: web.Context.Name, Help: "模板文件"}
|
||||||
|
|
||||||
web.Caches["directory"] = &ctx.Cache{Name: "directory", Value: m.Confx("directory", arg, 0), Help: "服务目录"}
|
web.Caches["directory"] = &ctx.Cache{Name: "directory", Value: m.Confx("directory", arg, 0), Help: "服务目录"}
|
||||||
web.Caches["route"] = &ctx.Cache{Name: "route", Value: "/" + web.Context.Name + "/", Help: "模块路由"}
|
web.Caches["route"] = &ctx.Cache{Name: "route", Value: "/" + web.Context.Name + "/", Help: "模块路由"}
|
||||||
web.Caches["register"] = &ctx.Cache{Name: "register(yes/no)", Value: "no", Help: "是否已初始化"}
|
web.Caches["register"] = &ctx.Cache{Name: "register(yes/no)", Value: "no", Help: "是否已初始化"}
|
||||||
web.Caches["master"] = &ctx.Cache{Name: "master(yes/no)", Value: "no", Help: "服务入口"}
|
web.Caches["master"] = &ctx.Cache{Name: "master(yes/no)", Value: "no", Help: "服务入口"}
|
||||||
|
|
||||||
web.ServeMux = http.NewServeMux()
|
web.ServeMux = http.NewServeMux()
|
||||||
|
web.Template = template.New("render").Funcs(ctx.CGI)
|
||||||
|
web.Template.ParseGlob(path.Join(m.Conf("template_dir"), "/*.tmpl"))
|
||||||
|
web.Template.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("template_sub"), "/*.tmpl"))
|
||||||
return web
|
return web
|
||||||
}
|
}
|
||||||
func (web *WEB) Start(m *ctx.Message, arg ...string) bool {
|
func (web *WEB) Start(m *ctx.Message, arg ...string) bool {
|
||||||
m.Cap("directory", m.Confx("directory", arg, 0))
|
m.Cap("directory", m.Confx("directory", arg, 0))
|
||||||
|
|
||||||
|
render := m.Target().Commands["/render"]
|
||||||
|
|
||||||
m.Travel(func(m *ctx.Message, i int) bool {
|
m.Travel(func(m *ctx.Message, i int) bool {
|
||||||
if h, ok := m.Target().Server.(MUX); ok && m.Cap("register") == "no" {
|
if h, ok := m.Target().Server.(MUX); ok && m.Cap("register") == "no" {
|
||||||
m.Cap("register", "yes")
|
m.Cap("register", "yes")
|
||||||
@ -193,10 +202,15 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool {
|
|||||||
s.Handle(m.Cap("route"), http.StripPrefix(path.Dir(m.Cap("route")), h))
|
s.Handle(m.Cap("route"), http.StripPrefix(path.Dir(m.Cap("route")), h))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.Target().Commands["/render"] == nil {
|
||||||
|
m.Target().Commands["/render"] = render
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := m.Target().Message()
|
||||||
for k, x := range m.Target().Commands {
|
for k, x := range m.Target().Commands {
|
||||||
if k[0] == '/' {
|
if k[0] == '/' {
|
||||||
m.Log("info", "route: %s", k)
|
m.Log("info", "route: %s", k)
|
||||||
h.HandleCmd(m, k, x)
|
h.HandleCmd(msg, k, x)
|
||||||
m.Capi("nroute", 1)
|
m.Capi("nroute", 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,19 +223,23 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if len(arg) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
web.Caches["protocol"] = &ctx.Cache{Name: "protocol", Value: m.Confx("protocol", arg, 2), Help: "服务协议"}
|
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: "服务地址"}
|
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")))
|
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" {
|
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["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: "服务密钥"}
|
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", "cert [%s]", m.Cap("cert"))
|
||||||
m.Log("info", "key [%s]", m.Cap("key"))
|
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 {
|
} else {
|
||||||
web.server.ListenAndServe()
|
web.Server.ListenAndServe()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -250,51 +268,15 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
"cert": &ctx.Config{Name: "cert", Value: "etc/cert.pem", Help: "路由数量"},
|
"cert": &ctx.Config{Name: "cert", Value: "etc/cert.pem", Help: "路由数量"},
|
||||||
"key": &ctx.Config{Name: "key", Value: "etc/key.pem", Help: "路由数量"},
|
"key": &ctx.Config{Name: "key", Value: "etc/key.pem", Help: "路由数量"},
|
||||||
|
|
||||||
"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: "模板路径"},
|
"template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template", Help: "模板路径"},
|
||||||
|
"template_debug": &ctx.Config{Name: "template_debug", Value: "true", Help: "模板调试"},
|
||||||
"componet_context": &ctx.Config{Name: "component_context", Value: "nfs", Help: "默认模块"},
|
"componet_context": &ctx.Config{Name: "component_context", Value: "nfs", Help: "默认模块"},
|
||||||
"componet_command": &ctx.Config{Name: "component_command", Value: "pwd", Help: "默认命令"},
|
"componet_command": &ctx.Config{Name: "component_command", Value: "pwd", Help: "默认命令"},
|
||||||
"componet_group": &ctx.Config{Name: "component_group", Value: "index", Help: "默认组件"},
|
"componet_group": &ctx.Config{Name: "component_group", Value: "index", Help: "默认组件"},
|
||||||
"componet": &ctx.Config{Name: "componet", Value: map[string]interface{}{
|
"componet": &ctx.Config{Name: "componet", Value: map[string]interface{}{
|
||||||
"login": []interface{}{
|
|
||||||
map[string]interface{}{"name": "head", "template": "head"},
|
|
||||||
map[string]interface{}{"name": "userinfo", "help": "userinfo",
|
|
||||||
"context": "aaa", "command": "userinfo", "arguments": []interface{}{"@sessid"},
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "login", "help": "login", "template": "componet",
|
|
||||||
"context": "aaa", "command": "login", "arguments": []interface{}{"@username", "@password"},
|
|
||||||
"inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "username", "label": "username"},
|
|
||||||
map[string]interface{}{"type": "password", "name": "password", "label": "password"},
|
|
||||||
map[string]interface{}{"type": "button", "label": "login"},
|
|
||||||
},
|
|
||||||
"display_append": "", "display_result": "", "result_reload": "10",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "tail", "template": "tail"},
|
|
||||||
},
|
|
||||||
"index": []interface{}{
|
"index": []interface{}{
|
||||||
map[string]interface{}{"name": "head", "template": "head"},
|
map[string]interface{}{"name": "head", "template": "head"},
|
||||||
map[string]interface{}{"name": "clipbaord", "help": "clipbaord", "template": "clipboard"},
|
map[string]interface{}{"name": "clipbaord", "help": "clipbaord", "template": "clipboard"},
|
||||||
map[string]interface{}{"name": "buffer", "help": "buffer", "template": "componet",
|
|
||||||
"context": "cli", "command": "tmux", "arguments": []interface{}{"buffer"}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "limit", "label": "limit", "value": "3"},
|
|
||||||
map[string]interface{}{"type": "text", "name": "index", "label": "index"},
|
|
||||||
map[string]interface{}{"type": "button", "label": "refresh"},
|
|
||||||
},
|
|
||||||
"pre_run": true,
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "command", "help": "command", "template": "componet",
|
|
||||||
"context": "cli.shell1", "command": "source", "arguments": []interface{}{"@cmd"},
|
|
||||||
"inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "cmd", "value": "",
|
|
||||||
"class": "cmd", "clipstack": "clistack",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "time", "help": "time", "template": "componet",
|
map[string]interface{}{"name": "time", "help": "time", "template": "componet",
|
||||||
"context": "cli", "command": "time", "arguments": []interface{}{"@string"},
|
"context": "cli", "command": "time", "arguments": []interface{}{"@string"},
|
||||||
"inputs": []interface{}{
|
"inputs": []interface{}{
|
||||||
@ -305,83 +287,6 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
map[string]interface{}{"type": "button", "label": "refresh"},
|
map[string]interface{}{"type": "button", "label": "refresh"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
map[string]interface{}{"name": "json", "help": "json", "template": "componet",
|
|
||||||
"context": "nfs", "command": "json", "arguments": []interface{}{"@string"},
|
|
||||||
"inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "string", "label": "string"},
|
|
||||||
map[string]interface{}{"type": "button", "label": "refresh"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "upload", "help": "upload", "template": "componet",
|
|
||||||
"form_type": "upload",
|
|
||||||
"inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "file", "name": "upload"},
|
|
||||||
map[string]interface{}{"type": "submit", "value": "submit"},
|
|
||||||
},
|
|
||||||
"display_result": "",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "dir", "help": "dir", "template": "componet",
|
|
||||||
"context": "nfs", "command": "dir", "arguments": []interface{}{"@dir",
|
|
||||||
"dir_deep", "no", "dir_name", "name", "dir_info", "",
|
|
||||||
"dir_link", "<a class='download' data-type='%s'>%s<a>",
|
|
||||||
},
|
|
||||||
"pre_run": true,
|
|
||||||
"inputs": []interface{}{
|
|
||||||
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": "is_dir", "value": "is_dir"},
|
|
||||||
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_r", "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{}{"type": "text", "name": "dir", "label": "dir"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "web_site", "help": "web_site", "template": "componet",
|
|
||||||
"context": "web", "command": "config", "arguments": []interface{}{
|
|
||||||
"web_site", "format_field", "site", "<a href='%s'>%s<a>",
|
|
||||||
},
|
|
||||||
"display_result": "",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "prompt", "help": "prompt", "template": "componet",
|
|
||||||
"context": "nfs.stdio", "command": "prompt", "arguments": []interface{}{"@string"},
|
|
||||||
"inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "string", "label": "string"},
|
|
||||||
map[string]interface{}{"type": "button", "label": "refresh"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "exec", "help": "exec", "template": "componet",
|
|
||||||
"context": "nfs.stdio", "command": "exec", "arguments": []interface{}{"@string"},
|
|
||||||
"inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "string"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "show", "help": "show", "template": "componet",
|
|
||||||
"context": "nfs.stdio", "command": "show", "arguments": []interface{}{"\n", "@string", "\n"},
|
|
||||||
"inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "string", "label": "string"},
|
|
||||||
map[string]interface{}{"type": "button", "label": "refresh"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "tail", "template": "tail"},
|
map[string]interface{}{"name": "tail", "template": "tail"},
|
||||||
},
|
},
|
||||||
}, Help: "组件列表"},
|
}, Help: "组件列表"},
|
||||||
@ -599,6 +504,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
m.Spawn().Cmd("open", url)
|
m.Spawn().Cmd("open", url)
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
|
|
||||||
"serve": &ctx.Command{Name: "serve [directory [address [protocol [cert [key]]]]", Help: "启动服务, directory: 服务路径, address: 服务地址, protocol: 服务协议(https/http), cert: 服务证书, key: 服务密钥", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"serve": &ctx.Command{Name: "serve [directory [address [protocol [cert [key]]]]", Help: "启动服务, directory: 服务路径, address: 服务地址, protocol: 服务协议(https/http), cert: 服务证书, key: 服务密钥", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
m.Set("detail", arg...).Target().Start(m)
|
m.Set("detail", arg...).Target().Start(m)
|
||||||
}},
|
}},
|
||||||
@ -660,26 +566,26 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
"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 web, ok := m.Target().Server.(*WEB); m.Assert(ok) {
|
||||||
if len(arg) == 0 {
|
if len(arg) == 0 {
|
||||||
for _, v := range web.template.Templates() {
|
for _, v := range web.Template.Templates() {
|
||||||
m.Add("append", "name", v.Name())
|
m.Add("append", "name", v.Name())
|
||||||
}
|
}
|
||||||
m.Sort("name").Table()
|
m.Sort("name").Table()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if web.template == nil {
|
if web.Template == nil {
|
||||||
web.template = template.New("render").Funcs(ctx.CGI)
|
web.Template = template.New("render").Funcs(ctx.CGI)
|
||||||
}
|
}
|
||||||
|
|
||||||
dir := path.Join(m.Confx("template_dir", arg, 1), arg[0])
|
dir := path.Join(m.Confx("template_dir", arg, 1), arg[0])
|
||||||
if t, e := web.template.ParseGlob(dir); e == nil {
|
if t, e := web.Template.ParseGlob(dir); e == nil {
|
||||||
web.template = t
|
web.Template = t
|
||||||
} else {
|
} else {
|
||||||
m.Log("info", "%s", e)
|
m.Log("info", "%s", e)
|
||||||
if len(arg) > 1 {
|
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 {
|
} else {
|
||||||
tmpl, e := web.template.Clone()
|
tmpl, e := web.Template.Clone()
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
tmpl.Funcs(ctx.CGI)
|
tmpl.Funcs(ctx.CGI)
|
||||||
|
|
||||||
@ -765,16 +671,21 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
m.Append("redirect", m.Option("referer"))
|
m.Append("redirect", m.Option("referer"))
|
||||||
}},
|
}},
|
||||||
"/render": &ctx.Command{Name: "/render template", Help: "渲染模板, template: 模板名称", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/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) {
|
if web, ok := m.Target().Server.(*WEB); m.Assert(ok) {
|
||||||
accept_json := strings.HasPrefix(m.Option("accept"), "application/json")
|
accept_json := strings.HasPrefix(m.Option("accept"), "application/json")
|
||||||
list := []interface{}{}
|
list := []interface{}{}
|
||||||
|
|
||||||
// tmpl, e := web.template.Clone()
|
// tmpl, e := web.Template.Clone()
|
||||||
// m.Assert(e)
|
// m.Assert(e)
|
||||||
// tmpl.Funcs(ctx.CGI)
|
// tmpl.Funcs(ctx.CGI)
|
||||||
//
|
//
|
||||||
tmpl := template.New("render").Funcs(ctx.CGI)
|
|
||||||
tmpl.ParseGlob(fmt.Sprintf("%s/context/usr/template/common/base.tmpl", os.Getenv("HOME")))
|
tmpl := web.Template
|
||||||
|
if m.Confs("template_debug") {
|
||||||
|
tmpl = template.New("render").Funcs(ctx.CGI)
|
||||||
|
tmpl.ParseGlob(path.Join(m.Conf("template_dir"), "/*.tmpl"))
|
||||||
|
tmpl.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("template_sub"), "/*.tmpl"))
|
||||||
|
}
|
||||||
|
|
||||||
w := m.Optionv("response").(http.ResponseWriter)
|
w := m.Optionv("response").(http.ResponseWriter)
|
||||||
if accept_json {
|
if accept_json {
|
||||||
|
@ -1,650 +1,151 @@
|
|||||||
package code
|
package code
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"contexts/ctx"
|
"contexts/ctx"
|
||||||
"contexts/web"
|
"contexts/web"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"html/template"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type CODE struct {
|
|
||||||
web.WEB
|
|
||||||
}
|
|
||||||
|
|
||||||
// yac := m.Sess("tags", m.Sess("yac").Cmd("scan"))
|
|
||||||
// yac.Cmd("train", "void", "void", "[\t ]+")
|
|
||||||
// yac.Cmd("train", "other", "other", "[^\n]+")
|
|
||||||
// yac.Cmd("train", "key", "key", "[A-Za-z_][A-Za-z_0-9]*")
|
|
||||||
// yac.Cmd("train", "code", "def", "def", "key", "(", "other")
|
|
||||||
// yac.Cmd("train", "code", "def", "class", "key", "other")
|
|
||||||
// yac.Cmd("train", "code", "struct", "struct", "key", "\\{")
|
|
||||||
// yac.Cmd("train", "code", "struct", "\\}", "key", ";")
|
|
||||||
// yac.Cmd("train", "code", "struct", "typedef", "struct", "key", "key", ";")
|
|
||||||
// yac.Cmd("train", "code", "function", "key", "\\*", "key", "(", "other")
|
|
||||||
// yac.Cmd("train", "code", "function", "key", "key", "(", "other")
|
|
||||||
// yac.Cmd("train", "code", "variable", "struct", "key", "key", "other")
|
|
||||||
// yac.Cmd("train", "code", "define", "#define", "key", "other")
|
|
||||||
//
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "code", Help: "代码中心",
|
var Index = &ctx.Context{Name: "code", Help: "代码中心",
|
||||||
Caches: map[string]*ctx.Cache{},
|
Caches: map[string]*ctx.Cache{},
|
||||||
Configs: map[string]*ctx.Config{
|
Configs: map[string]*ctx.Config{
|
||||||
"library_dir": &ctx.Config{Name: "library_dir", Value: "usr", Help: "通用模板路径"},
|
"web_site": &ctx.Config{Name: "web_site", Value: []interface{}{
|
||||||
"template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template/", Help: "通用模板路径"},
|
map[string]interface{}{"_name": "MDN", "site": "https://developer.mozilla.org"},
|
||||||
"common_tmpl": &ctx.Config{Name: "common_tmpl", Value: "common/*.html", Help: "通用模板路径"},
|
map[string]interface{}{"_name": "github", "site": "https://github.com"},
|
||||||
"common_main": &ctx.Config{Name: "common_main", Value: "main.html", Help: "通用模板框架"},
|
}, Help: "web_site"},
|
||||||
"upload_tmpl": &ctx.Config{Name: "upload_tmpl", Value: "upload.html", Help: "上传文件模板"},
|
"componet_command": &ctx.Config{Name: "component_command", Value: "pwd", Help: "默认命令"},
|
||||||
"upload_main": &ctx.Config{Name: "upload_main", Value: "main.html", Help: "上传文件框架"},
|
"componet_group": &ctx.Config{Name: "component_group", Value: "index", Help: "默认组件"},
|
||||||
"travel_tmpl": &ctx.Config{Name: "travel_tmpl", Value: "travel.html", Help: "浏览模块模板"},
|
"componet": &ctx.Config{Name: "componet", Value: map[string]interface{}{
|
||||||
"travel_main": &ctx.Config{Name: "travel_main", Value: "main.html", Help: "浏览模块框架"},
|
|
||||||
|
|
||||||
"check": &ctx.Config{Name: "check", Value: map[string]interface{}{
|
|
||||||
"login": []interface{}{
|
"login": []interface{}{
|
||||||
map[string]interface{}{
|
map[string]interface{}{"name": "head", "template": "head"},
|
||||||
"session": "aaa",
|
map[string]interface{}{"name": "userinfo", "help": "userinfo",
|
||||||
"module": "aaa", "command": "login",
|
"context": "aaa", "command": "userinfo", "arguments": []interface{}{"@sessid"},
|
||||||
"variable": []interface{}{"$sessid"},
|
|
||||||
"template": "login", "title": "login",
|
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
map[string]interface{}{"name": "login", "help": "login", "template": "componet",
|
||||||
"module": "aaa", "command": "login",
|
"context": "aaa", "command": "login", "arguments": []interface{}{"@username", "@password"},
|
||||||
"variable": []interface{}{"$username", "$password"},
|
"inputs": []interface{}{
|
||||||
"template": "login", "title": "login",
|
map[string]interface{}{"type": "text", "name": "username", "label": "username"},
|
||||||
|
map[string]interface{}{"type": "password", "name": "password", "label": "password"},
|
||||||
|
map[string]interface{}{"type": "button", "label": "login"},
|
||||||
|
},
|
||||||
|
"display_append": "", "display_result": "", "result_reload": "10",
|
||||||
|
},
|
||||||
|
map[string]interface{}{"name": "tail", "template": "tail"},
|
||||||
|
},
|
||||||
|
"index": []interface{}{
|
||||||
|
map[string]interface{}{"name": "head", "template": "head"},
|
||||||
|
map[string]interface{}{"name": "clipbaord", "help": "clipbaord", "template": "clipboard"},
|
||||||
|
map[string]interface{}{"name": "buffer", "help": "buffer", "template": "componet",
|
||||||
|
"context": "cli", "command": "tmux", "arguments": []interface{}{"buffer"}, "inputs": []interface{}{
|
||||||
|
map[string]interface{}{"type": "text", "name": "limit", "label": "limit", "value": "3"},
|
||||||
|
map[string]interface{}{"type": "text", "name": "index", "label": "index"},
|
||||||
|
map[string]interface{}{"type": "button", "label": "refresh"},
|
||||||
|
},
|
||||||
|
"pre_run": true,
|
||||||
|
},
|
||||||
|
map[string]interface{}{"name": "command", "help": "command", "template": "componet",
|
||||||
|
"context": "cli.shell1", "command": "source", "arguments": []interface{}{"@cmd"},
|
||||||
|
"inputs": []interface{}{
|
||||||
|
map[string]interface{}{"type": "text", "name": "cmd", "value": "",
|
||||||
|
"class": "cmd", "clipstack": "clistack",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"right": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"module": "web", "command": "right",
|
|
||||||
"variable": []interface{}{"$username", "check", "command", "/index", "dir", "$dir"},
|
|
||||||
"template": "notice", "title": "notice",
|
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
map[string]interface{}{"name": "time", "help": "time", "template": "componet",
|
||||||
"module": "aaa", "command": "login",
|
"context": "cli", "command": "time", "arguments": []interface{}{"@string"},
|
||||||
"variable": []interface{}{"username", "password"},
|
"inputs": []interface{}{
|
||||||
"template": "login", "title": "login",
|
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"},
|
||||||
|
map[string]interface{}{"type": "button", "label": "refresh"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, Help: "执行条件"},
|
map[string]interface{}{"name": "json", "help": "json", "template": "componet",
|
||||||
"auto_create": &ctx.Config{Name: "auto_create(true/false)", Value: "true", Help: "路由数量"},
|
"context": "nfs", "command": "json", "arguments": []interface{}{"@string"},
|
||||||
"refresh_time": &ctx.Config{Name: "refresh_time(ms)", Value: "1000", Help: "路由数量"},
|
"inputs": []interface{}{
|
||||||
"define": &ctx.Config{Name: "define", Value: map[string]interface{}{
|
map[string]interface{}{"type": "text", "name": "string", "label": "string"},
|
||||||
"ngx_command_t": map[string]interface{}{
|
map[string]interface{}{"type": "button", "label": "refresh"},
|
||||||
"position": []interface{}{map[string]interface{}{
|
|
||||||
"file": "nginx-1.15.2/src/core/ngx_core.h",
|
|
||||||
"line": "22",
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
"ngx_command_s": map[string]interface{}{
|
|
||||||
"position": map[string]interface{}{
|
|
||||||
"file": "nginx-1.15.2/src/core/ngx_conf_file.h",
|
|
||||||
"line": "77",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, Help: "路由数量"},
|
map[string]interface{}{"name": "upload", "help": "upload", "template": "componet",
|
||||||
"index": &ctx.Config{Name: "index", Value: map[string]interface{}{
|
"form_type": "upload",
|
||||||
"duyu": []interface{}{
|
"inputs": []interface{}{
|
||||||
map[string]interface{}{
|
map[string]interface{}{"type": "file", "name": "upload"},
|
||||||
"template": "userinfo", "title": "userinfo",
|
map[string]interface{}{"type": "submit", "value": "submit"},
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
"display_result": "",
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"module": "aaa", "command": "lark",
|
|
||||||
"argument": []interface{}{},
|
|
||||||
"template": "append", "title": "lark_friend",
|
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
map[string]interface{}{"name": "dir", "help": "dir", "template": "componet",
|
||||||
"module": "aaa", "detail": []interface{}{"lark"},
|
"context": "nfs", "command": "dir", "arguments": []interface{}{"@dir",
|
||||||
"template": "detail", "title": "send_lark",
|
"dir_deep", "no", "dir_name", "name", "dir_info", "",
|
||||||
"option": map[string]interface{}{"ninput": 2},
|
"dir_link", "<a class='download' data-type='%s'>%s<a>",
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
"pre_run": true,
|
||||||
"module": "aaa", "command": "lark",
|
"inputs": []interface{}{
|
||||||
"argument": []interface{}{"duyu"},
|
map[string]interface{}{"type": "choice", "name": "dir_type",
|
||||||
"template": "append", "title": "lark",
|
"label": "dir_type", "value": "both", "choice": []interface{}{
|
||||||
},
|
map[string]interface{}{"name": "both", "value": "both"},
|
||||||
map[string]interface{}{
|
map[string]interface{}{"name": "file", "value": "file"},
|
||||||
"module": "nfs", "command": "dir",
|
map[string]interface{}{"name": "dir", "value": "dir"},
|
||||||
"argument": []interface{}{"dir_type", "all", "dir_deep", "false", "dir_field", "time size line filename", "sort_field", "time", "sort_order", "time_r"},
|
|
||||||
"template": "append", "title": "",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"shy": []interface{}{
|
map[string]interface{}{"type": "choice", "name": "sort_field",
|
||||||
map[string]interface{}{
|
"label": "sort_field", "value": "time", "choice": []interface{}{
|
||||||
"from": "root", "to": []interface{}{},
|
map[string]interface{}{"name": "filename", "value": "filename"},
|
||||||
"template": "userinfo", "title": "userinfo",
|
map[string]interface{}{"name": "is_dir", "value": "is_dir"},
|
||||||
},
|
map[string]interface{}{"name": "line", "value": "line"},
|
||||||
//文件服务
|
map[string]interface{}{"name": "size", "value": "size"},
|
||||||
map[string]interface{}{
|
map[string]interface{}{"name": "time", "value": "time"},
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"module": "nfs", "command": "dir",
|
|
||||||
"argument": []interface{}{"dir_type", "all", "dir_deep", "false", "dir_field", "time size line filename", "sort_field", "time", "sort_order", "time_r"},
|
|
||||||
"template": "append", "title": "",
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"template": "upload", "title": "upload",
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"template": "create", "title": "create",
|
|
||||||
},
|
|
||||||
//会话服务
|
|
||||||
map[string]interface{}{
|
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"module": "cli", "command": "system",
|
|
||||||
"argument": []interface{}{"tmux", "show-buffer"},
|
|
||||||
"template": "result", "title": "buffer",
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"module": "cli", "command": "system",
|
|
||||||
"argument": []interface{}{"tmux", "list-clients"},
|
|
||||||
"template": "result", "title": "client",
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"module": "cli", "command": "system",
|
|
||||||
"argument": []interface{}{"tmux", "list-sessions"},
|
|
||||||
"template": "result", "title": "session",
|
|
||||||
},
|
|
||||||
//格式转换
|
|
||||||
map[string]interface{}{
|
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"module": "cli", "detail": []interface{}{"time"},
|
|
||||||
"template": "detail", "title": "time",
|
|
||||||
"option": map[string]interface{}{"refresh": true, "ninput": 1},
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"module": "nfs", "detail": []interface{}{"json"},
|
|
||||||
"template": "detail", "title": "json",
|
|
||||||
"option": map[string]interface{}{"ninput": 1},
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"module": "nfs", "detail": []interface{}{"pwd"},
|
|
||||||
"template": "detail", "title": "pwd",
|
|
||||||
"option": map[string]interface{}{"refresh": true},
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"module": "nfs", "command": "git",
|
|
||||||
"argument": []interface{}{},
|
|
||||||
"template": "result", "title": "git",
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"from": "root", "to": []interface{}{},
|
|
||||||
"module": "web", "command": "/share",
|
|
||||||
"argument": []interface{}{},
|
|
||||||
"template": "share", "title": "share",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"notice": []interface{}{
|
map[string]interface{}{"type": "choice", "name": "sort_order",
|
||||||
map[string]interface{}{
|
"label": "sort_order", "value": "time_r", "choice": []interface{}{
|
||||||
"template": "userinfo", "title": "userinfo",
|
map[string]interface{}{"name": "str", "value": "str"},
|
||||||
},
|
map[string]interface{}{"name": "str_r", "value": "str_r"},
|
||||||
map[string]interface{}{
|
map[string]interface{}{"name": "int", "value": "int"},
|
||||||
"template": "notice", "title": "notice",
|
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"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"login": []interface{}{
|
map[string]interface{}{"type": "text", "name": "dir", "label": "dir"},
|
||||||
map[string]interface{}{
|
|
||||||
"template": "login", "title": "login",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"wiki": []interface{}{
|
map[string]interface{}{"name": "web_site", "help": "web_site", "template": "componet",
|
||||||
map[string]interface{}{
|
"context": "web", "command": "config", "arguments": []interface{}{
|
||||||
"template": "wiki_head", "title": "wiki_head",
|
"web_site", "format_field", "site", "<a href='%s'>%s<a>",
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
"display_result": "",
|
||||||
"template": "wiki_menu", "title": "wiki_menu",
|
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
map[string]interface{}{"name": "prompt", "help": "prompt", "template": "componet",
|
||||||
"module": "web", "command": "/wiki_list",
|
"context": "nfs.stdio", "command": "prompt", "arguments": []interface{}{"@string"},
|
||||||
"template": "wiki_list", "title": "wiki_list",
|
"inputs": []interface{}{
|
||||||
},
|
map[string]interface{}{"type": "text", "name": "string", "label": "string"},
|
||||||
map[string]interface{}{
|
map[string]interface{}{"type": "button", "label": "refresh"},
|
||||||
"module": "web", "command": "/wiki_body",
|
|
||||||
"template": "wiki_body", "title": "wiki_body",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, Help: "资源列表"},
|
map[string]interface{}{"name": "exec", "help": "exec", "template": "componet",
|
||||||
|
"context": "nfs.stdio", "command": "exec", "arguments": []interface{}{"@string"},
|
||||||
|
"inputs": []interface{}{
|
||||||
|
map[string]interface{}{"type": "text", "name": "string"},
|
||||||
},
|
},
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"/demo": &ctx.Command{Name: "/demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
||||||
m.Echo("demo")
|
|
||||||
}},
|
|
||||||
"/render": &ctx.Command{Name: "/render index", Help: "模板响应, main: 模板入口, tmpl: 附加模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
||||||
w := m.Optionv("response").(http.ResponseWriter)
|
|
||||||
w.Header().Add("Content-Type", "text/html")
|
|
||||||
m.Optioni("ninput", 0)
|
|
||||||
|
|
||||||
tpl := template.New("render").Funcs(ctx.CGI)
|
|
||||||
tpl = template.Must(tpl.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("common_tmpl"))))
|
|
||||||
tpl = template.Must(tpl.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("upload_tmpl"))))
|
|
||||||
|
|
||||||
replace := [][]byte{
|
|
||||||
[]byte{27, 91, 51, 50, 109}, []byte("<span style='color:red'>"),
|
|
||||||
[]byte{27, 91, 51, 49, 109}, []byte("<span style='color:green'>"),
|
|
||||||
[]byte{27, 91, 109}, []byte("</span>"),
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Confv("index", arg[0]) == nil {
|
|
||||||
arg[0] = "notice"
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Assert(tpl.ExecuteTemplate(w, "head", m))
|
|
||||||
for _, v := range m.Confv("index", arg[0]).([]interface{}) {
|
|
||||||
if v == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
val := v.(map[string]interface{})
|
|
||||||
//命令模板
|
|
||||||
if detail, ok := val["detail"].([]interface{}); ok {
|
|
||||||
msg := m.Spawn().Add("detail", detail[0].(string), detail[1:])
|
|
||||||
msg.Option("module", val["module"])
|
|
||||||
msg.Option("title", val["title"])
|
|
||||||
if option, ok := val["option"].(map[string]interface{}); ok {
|
|
||||||
for k, v := range option {
|
|
||||||
msg.Option(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), msg))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//执行命令
|
|
||||||
if _, ok := val["command"]; ok {
|
|
||||||
msg := m.Find(val["module"].(string)).Cmd(val["command"], val["argument"])
|
|
||||||
for i, v := range msg.Meta["result"] {
|
|
||||||
b := []byte(v)
|
|
||||||
for i := 0; i < len(replace)-1; i += 2 {
|
|
||||||
b = bytes.Replace(b, replace[i], replace[i+1], -1)
|
|
||||||
}
|
|
||||||
msg.Meta["result"][i] = string(b)
|
|
||||||
}
|
|
||||||
if msg.Option("title", val["title"]) == "" {
|
|
||||||
msg.Option("title", m.Option("dir"))
|
|
||||||
}
|
|
||||||
m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), msg))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//解析模板
|
|
||||||
if _, ok := val["template"]; ok {
|
|
||||||
m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), m))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Assert(tpl.ExecuteTemplate(w, "tail", m))
|
|
||||||
}},
|
|
||||||
|
|
||||||
"/check": &ctx.Command{Name: "/check arg...", Help: "权限检查, cache|config|command: 接口类型, name: 接口名称, args: 其它参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
||||||
if login := m.Spawn().Cmd("/login"); login.Has("template") {
|
|
||||||
m.Echo("no").Copy(login, "append")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if msg := m.Spawn().Cmd("right", m.Append("username"), "check", arg); !msg.Results(0) {
|
|
||||||
m.Echo("no").Append("message", "no right, please contact manager")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Echo("ok")
|
|
||||||
|
|
||||||
}},
|
|
||||||
"/login": &ctx.Command{Name: "/login", Help: "用户登录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
||||||
if m.Options("sessid") {
|
|
||||||
if aaa := m.Sess("aaa").Cmd("login", m.Option("sessid")); aaa.Results(0) {
|
|
||||||
m.Append("redirect", m.Option("referer"))
|
|
||||||
m.Append("username", aaa.Result(0))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
w := m.Optionv("response").(http.ResponseWriter)
|
|
||||||
if m.Options("username") && m.Options("password") {
|
|
||||||
if aaa := m.Sess("aaa").Cmd("login", m.Option("username"), m.Option("password")); aaa.Results(0) {
|
|
||||||
http.SetCookie(w, &http.Cookie{Name: "sessid", Value: aaa.Result(0)})
|
|
||||||
m.Append("redirect", m.Option("referer"))
|
|
||||||
m.Append("username", m.Option("username"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
|
||||||
m.Append("template", "login")
|
|
||||||
|
|
||||||
}},
|
|
||||||
"/lookup": &ctx.Command{Name: "user", Help: "应用示例", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
||||||
if len(arg) > 0 {
|
|
||||||
m.Option("service", arg[0])
|
|
||||||
}
|
|
||||||
msg := m.Sess("cli").Cmd("system", "sd", "lookup", m.Option("service"))
|
|
||||||
|
|
||||||
rs := strings.Split(msg.Result(0), "\n")
|
|
||||||
i := 0
|
|
||||||
for ; i < len(rs); i++ {
|
|
||||||
if len(rs[i]) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fields := strings.SplitN(rs[i], ": ", 2)
|
|
||||||
m.Append(fields[0], fields[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
lists := []interface{}{}
|
|
||||||
for i += 2; i < len(rs); i++ {
|
|
||||||
fields := strings.SplitN(rs[i], " ", 3)
|
|
||||||
if len(fields) < 3 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
lists = append(lists, map[string]interface{}{
|
|
||||||
"ip": fields[0],
|
|
||||||
"port": fields[1],
|
|
||||||
"tags": fields[2],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Appendv("lists", lists)
|
|
||||||
m.Log("log", "%v", lists)
|
|
||||||
}},
|
|
||||||
"upload": &ctx.Command{Name: "upload file", Help: "上传文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
||||||
msg := m.Spawn(m.Target())
|
|
||||||
msg.Cmd("get", "/upload", "method", "POST", "file", "file", arg[0])
|
|
||||||
m.Copy(msg, "result")
|
|
||||||
|
|
||||||
}},
|
|
||||||
"/travel": &ctx.Command{Name: "/travel", Help: "文件上传", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
||||||
// r := m.Optionv("request").(*http.Request)
|
|
||||||
// w := m.Optionv("response").(http.ResponseWriter)
|
|
||||||
|
|
||||||
if !m.Options("dir") {
|
|
||||||
m.Option("dir", "ctx")
|
|
||||||
}
|
|
||||||
|
|
||||||
check := m.Spawn().Cmd("/share", "/travel", "dir", m.Option("dir"))
|
|
||||||
if !check.Results(0) {
|
|
||||||
m.Copy(check, "append")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 权限检查
|
|
||||||
if m.Option("method") == "POST" {
|
|
||||||
if m.Options("domain") {
|
|
||||||
msg := m.Find("ssh", true)
|
|
||||||
msg.Detail(0, "send", "domain", m.Option("domain"), "context", "find", m.Option("dir"))
|
|
||||||
if m.Option("name") != "" {
|
|
||||||
msg.Add("detail", m.Option("name"))
|
|
||||||
}
|
|
||||||
if m.Options("value") {
|
|
||||||
value := []string{}
|
|
||||||
json.Unmarshal([]byte(m.Option("value")), &value)
|
|
||||||
if len(value) > 0 {
|
|
||||||
msg.Add("detail", value[0], value[1:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.CallBack(true, func(sub *ctx.Message) *ctx.Message {
|
|
||||||
m.Copy(sub, "result").Copy(sub, "append")
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := m.Find(m.Option("dir"), true)
|
|
||||||
if msg == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch m.Option("ccc") {
|
|
||||||
case "cache":
|
|
||||||
m.Echo(msg.Cap(m.Option("name")))
|
|
||||||
case "config":
|
|
||||||
if m.Has("value") {
|
|
||||||
m.Echo(msg.Conf(m.Option("name"), m.Option("value")))
|
|
||||||
} else {
|
|
||||||
m.Echo(msg.Conf(m.Option("name")))
|
|
||||||
}
|
|
||||||
case "command":
|
|
||||||
msg = msg.Spawn(msg.Target())
|
|
||||||
msg.Detail(0, m.Option("name"))
|
|
||||||
if m.Options("value") {
|
|
||||||
value := []string{}
|
|
||||||
json.Unmarshal([]byte(m.Option("value")), &value)
|
|
||||||
if len(value) > 0 {
|
|
||||||
msg.Add("detail", value[0], value[1:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.Cmd()
|
|
||||||
m.Copy(msg, "result").Copy(msg, "append")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析模板
|
|
||||||
m.Set("append", "tmpl", "userinfo", "share")
|
|
||||||
msg := m
|
|
||||||
for _, v := range []string{"cache", "config", "command", "module", "domain"} {
|
|
||||||
if m.Options("domain") {
|
|
||||||
msg = m.Find("ssh", true)
|
|
||||||
msg.Detail(0, "send", "domain", m.Option("domain"), "context", "find", m.Option("dir"), "list", v)
|
|
||||||
msg.CallBack(true, func(sub *ctx.Message) *ctx.Message {
|
|
||||||
msg.Copy(sub, "result").Copy(sub, "append")
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
msg = m.Spawn()
|
|
||||||
msg.Cmd("context", "find", msg.Option("dir"), "list", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(msg.Meta["append"]) > 0 {
|
|
||||||
msg.Option("current_module", m.Option("dir"))
|
|
||||||
msg.Option("current_domain", m.Option("domain"))
|
|
||||||
m.Add("option", "tmpl", v)
|
|
||||||
m.Sess(v, msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Append("template", m.Conf("travel_main"), m.Conf("travel_tmpl"))
|
|
||||||
|
|
||||||
}},
|
|
||||||
"/index/": &ctx.Command{Name: "/index", Help: "网页门户", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
||||||
r := m.Optionv("request").(*http.Request)
|
|
||||||
w := m.Optionv("response").(http.ResponseWriter)
|
|
||||||
|
|
||||||
if login := m.Spawn().Cmd("/login"); login.Has("template") {
|
|
||||||
m.Echo("no").Copy(login, "append")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.Option("username", m.Append("username"))
|
|
||||||
|
|
||||||
//权限检查
|
|
||||||
dir := m.Option("dir", path.Join(m.Cap("directory"), "local", m.Option("username"), m.Option("dir", strings.TrimPrefix(m.Option("path"), "/index"))))
|
|
||||||
// if check := m.Spawn(c).Cmd("/check", "command", "/index/", "dir", dir); !check.Results(0) {
|
|
||||||
// m.Copy(check, "append")
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
//执行命令
|
|
||||||
if m.Has("details") {
|
|
||||||
if m.Confs("check_right") {
|
|
||||||
if check := m.Spawn().Cmd("/check", "target", m.Option("module"), "command", m.Option("details")); !check.Results(0) {
|
|
||||||
m.Copy(check, "append")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := m.Find(m.Option("module")).Cmd(m.Optionv("details"))
|
|
||||||
m.Copy(msg, "result").Copy(msg, "append")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//下载文件
|
|
||||||
if s, e := os.Stat(dir); e == nil && !s.IsDir() {
|
|
||||||
http.ServeFile(w, r, dir)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !m.Options("module") {
|
|
||||||
m.Option("module", "web")
|
|
||||||
}
|
|
||||||
//浏览目录
|
|
||||||
m.Append("template", m.Append("username"))
|
|
||||||
m.Option("page_title", "index")
|
|
||||||
|
|
||||||
}},
|
|
||||||
"/create": &ctx.Command{Name: "/create", Help: "创建目录或文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
||||||
// if check := m.Spawn().Cmd("/share", "/upload", "dir", m.Option("dir")); !check.Results(0) {
|
|
||||||
// m.Copy(check, "append")
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
r := m.Optionv("request").(*http.Request)
|
|
||||||
if m.Option("method") == "POST" {
|
|
||||||
if m.Options("filename") { //添加文件或目录
|
|
||||||
name := path.Join(m.Option("dir"), m.Option("filename"))
|
|
||||||
if _, e := os.Stat(name); e != nil {
|
|
||||||
if m.Options("content") {
|
|
||||||
f, e := os.Create(name)
|
|
||||||
m.Assert(e)
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
_, e = f.WriteString(m.Option("content"))
|
|
||||||
m.Assert(e)
|
|
||||||
} else {
|
|
||||||
e = os.Mkdir(name, 0766)
|
|
||||||
m.Assert(e)
|
|
||||||
}
|
|
||||||
m.Append("message", name, " create success!")
|
|
||||||
} else {
|
|
||||||
m.Append("message", name, " already exist!")
|
|
||||||
}
|
|
||||||
} else { //上传文件
|
|
||||||
file, header, e := r.FormFile("file")
|
|
||||||
m.Assert(e)
|
|
||||||
|
|
||||||
name := path.Join(m.Option("dir"), header.Filename)
|
|
||||||
|
|
||||||
if _, e := os.Stat(name); e != nil {
|
|
||||||
f, e := os.Create(name)
|
|
||||||
m.Assert(e)
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
_, e = io.Copy(f, file)
|
|
||||||
m.Assert(e)
|
|
||||||
m.Append("message", name, " upload success!")
|
|
||||||
} else {
|
|
||||||
m.Append("message", name, " already exist!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Append("redirect", m.Option("referer"))
|
|
||||||
|
|
||||||
}},
|
|
||||||
"/share": &ctx.Command{Name: "/share arg...", Help: "资源共享", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
||||||
if check := m.Spawn().Cmd("/check", "target", m.Option("module"), m.Optionv("share")); !check.Results(0) {
|
|
||||||
m.Copy(check, "append")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.Option("username", m.Append("username"))
|
|
||||||
|
|
||||||
// if m.Options("friend") && m.Options("module") {
|
|
||||||
// m.Copy(m.Appendv("aaa").(*ctx.Message).Find(m.Option("module")).Cmd("right", m.Option("friend"), m.Option("action"), m.Optionv("share")), "result")
|
|
||||||
// if m.Confv("index", m.Option("friend")) == nil {
|
|
||||||
// m.Confv("index", m.Option("friend"), m.Confv("index", m.Append("username")))
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// msg := m.Spawn().Cmd("right", "target", m.Option("module"), m.Append("username"), "show", "context")
|
|
||||||
// m.Copy(msg, "append")
|
|
||||||
if m.Options("friend") && m.Options("template") && m.Options("title") {
|
|
||||||
for i, v := range m.Confv("index", m.Option("username")).([]interface{}) {
|
|
||||||
if v == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
val := v.(map[string]interface{})
|
|
||||||
if val["template"].(string) == m.Option("template") && val["title"].(string) == m.Option("title") {
|
|
||||||
if m.Option("action") == "del" {
|
|
||||||
friends := m.Confv("index", strings.Join([]string{m.Option("username"), fmt.Sprintf("%d", i), "to"}, ".")).([]interface{})
|
|
||||||
for j, x := range friends {
|
|
||||||
if x.(string) == m.Option("friend") {
|
|
||||||
m.Confv("index", strings.Join([]string{m.Option("username"), fmt.Sprintf("%d", i), "to", fmt.Sprintf("%d", j)}, "."), nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
temps := m.Confv("index", strings.Join([]string{m.Option("friend")}, ".")).([]interface{})
|
|
||||||
for j, x := range temps {
|
|
||||||
if x == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
val = x.(map[string]interface{})
|
|
||||||
if val["template"].(string) == m.Option("template") && val["title"].(string) == m.Option("title") {
|
|
||||||
m.Confv("index", strings.Join([]string{m.Option("friend"), fmt.Sprintf("%d", j)}, "."), nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Confv("index", m.Option("friend")) == nil && !m.Confs("auto_create") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
m.Confv("index", strings.Join([]string{m.Option("username"), fmt.Sprintf("%d", i), "to", "-2"}, "."), m.Option("friend"))
|
|
||||||
|
|
||||||
item := map[string]interface{}{
|
|
||||||
"template": val["template"],
|
|
||||||
"title": val["title"],
|
|
||||||
"from": m.Option("username"),
|
|
||||||
}
|
|
||||||
if val["command"] != nil {
|
|
||||||
item["module"] = val["module"]
|
|
||||||
item["command"] = val["command"]
|
|
||||||
item["argument"] = val["argument"]
|
|
||||||
} else if val["detail"] != nil {
|
|
||||||
item["module"] = val["module"]
|
|
||||||
item["detail"] = val["detail"]
|
|
||||||
item["option"] = val["option"]
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Confv("index", strings.Join([]string{m.Option("friend"), fmt.Sprintf("%d", -2)}, "."), item)
|
|
||||||
m.Appendv("aaa").(*ctx.Message).Spawn(c).Cmd("right", m.Option("friend"), "add", "command", "/index/", "dir", m.Cap("directory"))
|
|
||||||
os.Mkdir(path.Join(m.Cap("directory"), m.Option("friend")), 0666)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, v := range m.Confv("index", m.Option("username")).([]interface{}) {
|
|
||||||
val := v.(map[string]interface{})
|
|
||||||
m.Add("append", "template", val["template"])
|
|
||||||
m.Add("append", "titles", val["title"])
|
|
||||||
m.Add("append", "from", val["from"])
|
|
||||||
m.Add("append", "to", "")
|
|
||||||
if val["to"] == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, u := range val["to"].([]interface{}) {
|
|
||||||
m.Add("append", "template", val["template"])
|
|
||||||
m.Add("append", "titles", val["title"])
|
|
||||||
m.Add("append", "from", val["from"])
|
|
||||||
m.Add("append", "to", u)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
|
map[string]interface{}{"name": "show", "help": "show", "template": "componet",
|
||||||
|
"context": "nfs.stdio", "command": "show", "arguments": []interface{}{"\n", "@string", "\n"},
|
||||||
|
"inputs": []interface{}{
|
||||||
|
map[string]interface{}{"type": "text", "name": "string", "label": "string"},
|
||||||
|
map[string]interface{}{"type": "button", "label": "refresh"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
map[string]interface{}{"name": "tail", "template": "tail"},
|
||||||
|
},
|
||||||
|
}, Help: "组件列表"},
|
||||||
|
},
|
||||||
|
Commands: map[string]*ctx.Command{},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
code := &CODE{}
|
code := &web.WEB{}
|
||||||
code.Context = Index
|
code.Context = Index
|
||||||
web.Index.Register(Index, code)
|
web.Index.Register(Index, code)
|
||||||
}
|
}
|
||||||
|
@ -1,48 +1,119 @@
|
|||||||
package wiki
|
package wiki
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"contexts/ctx"
|
"contexts/ctx"
|
||||||
"contexts/web"
|
"contexts/web"
|
||||||
"encoding/json"
|
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gomarkdown/markdown"
|
"github.com/gomarkdown/markdown"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"mime/multipart"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WIKI struct {
|
|
||||||
web.WEB
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "wiki", Help: "文档中心",
|
var Index = &ctx.Context{Name: "wiki", Help: "文档中心",
|
||||||
Caches: map[string]*ctx.Cache{},
|
Caches: map[string]*ctx.Cache{},
|
||||||
Configs: map[string]*ctx.Config{
|
Configs: map[string]*ctx.Config{
|
||||||
"which": &ctx.Config{Name: "which", Value: "redis.note", Help: "路由数量"},
|
|
||||||
"wiki_dir": &ctx.Config{Name: "wiki_dir", Value: "usr/wiki", Help: "路由数量"},
|
"wiki_dir": &ctx.Config{Name: "wiki_dir", Value: "usr/wiki", Help: "路由数量"},
|
||||||
|
"wiki_favor": &ctx.Config{Name: "wiki_favor", Value: "lamp.md", Help: "路由数量"},
|
||||||
|
"wiki_list": &ctx.Config{Name: "wiki_list", Value: []interface{}{}, Help: "路由数量"},
|
||||||
|
|
||||||
"wiki_list_show": &ctx.Config{Name: "wiki_list_show", Value: map[string]interface{}{
|
"wiki_list_show": &ctx.Config{Name: "wiki_list_show", Value: map[string]interface{}{
|
||||||
"md": true,
|
"md": true,
|
||||||
}, Help: "路由数量"},
|
}, Help: "路由数量"},
|
||||||
|
|
||||||
|
"componet_group": &ctx.Config{Name: "component_group", Value: "index", Help: "默认组件"},
|
||||||
|
"componet": &ctx.Config{Name: "componet", Value: map[string]interface{}{
|
||||||
|
"index": []interface{}{
|
||||||
|
map[string]interface{}{"name": "head", "template": "head"},
|
||||||
|
map[string]interface{}{"name": "header", "template": "header"},
|
||||||
|
map[string]interface{}{"name": "list", "template": "list",
|
||||||
|
"context": "web.wiki", "command": "wiki_list", "arguments": []interface{}{"h2", "int_r"},
|
||||||
|
"pre_run": true,
|
||||||
|
},
|
||||||
|
map[string]interface{}{"name": "text", "template": "text",
|
||||||
|
"context": "web.wiki", "command": "wiki_body", "arguments": []interface{}{"@wiki_favor"},
|
||||||
|
"pre_run": true,
|
||||||
|
},
|
||||||
|
map[string]interface{}{"name": "footer", "template": "footer"},
|
||||||
|
map[string]interface{}{"name": "tail", "template": "tail"},
|
||||||
|
},
|
||||||
|
}, Help: "组件列表"},
|
||||||
},
|
},
|
||||||
Commands: map[string]*ctx.Command{
|
Commands: map[string]*ctx.Command{
|
||||||
"/blog": &ctx.Command{Name: "/blog", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"wiki_list": &ctx.Command{Name: "wiki_list sort_field sort_order", Help: "wiki_list", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if m.Has("title") && m.Has("content") {
|
sort_field, sort_order := "h2", "int_r"
|
||||||
|
if len(arg) > 0 {
|
||||||
|
sort_field, arg = arg[0], arg[1:]
|
||||||
|
}
|
||||||
|
if len(arg) > 0 {
|
||||||
|
sort_order, arg = arg[0], arg[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Echo("blog service")
|
md, e := ioutil.ReadDir(m.Conf("wiki_dir"))
|
||||||
|
m.Assert(e)
|
||||||
|
|
||||||
|
for _, v := range md {
|
||||||
|
if strings.HasSuffix(v.Name(), ".md") {
|
||||||
|
f, e := os.Open(path.Join(m.Conf("wiki_dir"), v.Name()))
|
||||||
|
m.Assert(e)
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
title := ""
|
||||||
|
nline, ncode := 0, 0
|
||||||
|
h2, h3, h4 := 0, 0, 0
|
||||||
|
for bio := bufio.NewScanner(f); bio.Scan(); {
|
||||||
|
line := bio.Text()
|
||||||
|
nline++
|
||||||
|
|
||||||
|
if strings.HasPrefix(line, "## ") {
|
||||||
|
h2++
|
||||||
|
if title == "" {
|
||||||
|
title = line[3:]
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(line, "### ") {
|
||||||
|
h3++
|
||||||
|
} else if strings.HasPrefix(line, "#### ") {
|
||||||
|
h4++
|
||||||
|
} else if strings.HasPrefix(line, "```") {
|
||||||
|
ncode++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Add("append", "time", v.ModTime().Format("2006/01/02"))
|
||||||
|
m.Add("append", "file", v.Name())
|
||||||
|
m.Add("append", "size", v.Size())
|
||||||
|
|
||||||
|
m.Add("append", "line", nline)
|
||||||
|
m.Add("append", "code", ncode/2)
|
||||||
|
m.Add("append", "h4", h4)
|
||||||
|
m.Add("append", "h3", h3)
|
||||||
|
m.Add("append", "h2", h2)
|
||||||
|
m.Add("append", "title", title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.Sort(sort_field, sort_order).Table()
|
||||||
|
|
||||||
|
m.Target().Configs["wiki_list"].Value = []interface{}{}
|
||||||
|
m.Table(func(maps map[string]string, list []string, line int) bool {
|
||||||
|
if line > 0 {
|
||||||
|
m.Confv("wiki_list", -2, maps)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
}},
|
}},
|
||||||
|
"wiki_body": &ctx.Command{Name: "wiki_body", Help: "wiki_body", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
|
which := path.Join(m.Conf("wiki_dir"), m.Confx("wiki_favor", arg, 0))
|
||||||
|
if ls, e := ioutil.ReadFile(which); e == nil {
|
||||||
|
ls = markdown.ToHTML(ls, nil, nil)
|
||||||
|
m.Echo(string(ls))
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
|
||||||
"/wiki_tags": &ctx.Command{Name: "/wiki_tags ", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/wiki_tags": &ctx.Command{Name: "/wiki_tags ", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if len(arg) > 0 {
|
if len(arg) > 0 {
|
||||||
m.Option("dir", arg[0])
|
m.Option("dir", arg[0])
|
||||||
@ -347,269 +418,11 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心",
|
|||||||
m.Echo(string(b))
|
m.Echo(string(b))
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
"old_get": &ctx.Command{
|
|
||||||
Name: "get [method GET|POST] [file name filename] url arg...",
|
|
||||||
Help: "访问服务, method: 请求方法, file: 发送文件, url: 请求地址, arg: 请求参数",
|
|
||||||
Form: map[string]int{"method": 1, "content_type": 1, "headers": 2, "file": 2, "body_type": 1, "body": 1, "fields": 1, "value": 1, "json_route": 1, "json_key": 1},
|
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
||||||
if web, ok := m.Target().Server.(*web.WEB); m.Assert(ok) {
|
|
||||||
if web.Client == nil {
|
|
||||||
web.Client = &http.Client{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Has("value") {
|
|
||||||
args := strings.Split(m.Option("value"), " ")
|
|
||||||
values := []interface{}{}
|
|
||||||
for _, v := range args {
|
|
||||||
if len(v) > 1 && v[0] == '$' {
|
|
||||||
values = append(values, m.Cap(v[1:]))
|
|
||||||
} else {
|
|
||||||
values = append(values, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arg[0] = fmt.Sprintf(arg[0], values...)
|
|
||||||
}
|
|
||||||
|
|
||||||
method := m.Confx("method")
|
|
||||||
uri := web.Merge(m, arg[0], arg[1:]...)
|
|
||||||
m.Log("info", "%s %s", method, uri)
|
|
||||||
m.Echo("%s: %s\n", method, uri)
|
|
||||||
|
|
||||||
var body io.Reader
|
|
||||||
index := strings.Index(uri, "?")
|
|
||||||
content_type := ""
|
|
||||||
|
|
||||||
switch method {
|
|
||||||
case "POST":
|
|
||||||
if m.Options("file") {
|
|
||||||
file, e := os.Open(m.Meta["file"][1])
|
|
||||||
m.Assert(e)
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
if m.Option("body_type") == "json" {
|
|
||||||
content_type = "application/json"
|
|
||||||
body = file
|
|
||||||
break
|
|
||||||
}
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
writer := multipart.NewWriter(buf)
|
|
||||||
|
|
||||||
part, e := writer.CreateFormFile(m.Option("file"), filepath.Base(m.Meta["file"][1]))
|
|
||||||
m.Assert(e)
|
|
||||||
io.Copy(part, file)
|
|
||||||
|
|
||||||
for i := 0; i < len(arg)-1; i += 2 {
|
|
||||||
value := arg[i+1]
|
|
||||||
if len(arg[i+1]) > 1 {
|
|
||||||
switch arg[i+1][0] {
|
|
||||||
case '$':
|
|
||||||
value = m.Cap(arg[i+1][1:])
|
|
||||||
case '@':
|
|
||||||
value = m.Conf(arg[i+1][1:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writer.WriteField(arg[i], value)
|
|
||||||
}
|
|
||||||
|
|
||||||
content_type = writer.FormDataContentType()
|
|
||||||
body = buf
|
|
||||||
writer.Close()
|
|
||||||
} else if m.Option("body_type") == "json" {
|
|
||||||
if m.Options("body") {
|
|
||||||
data := []interface{}{}
|
|
||||||
for _, v := range arg[1:] {
|
|
||||||
if len(v) > 1 && v[0] == '$' {
|
|
||||||
v = m.Cap(v[1:])
|
|
||||||
}
|
|
||||||
data = append(data, v)
|
|
||||||
}
|
|
||||||
body = strings.NewReader(fmt.Sprintf(m.Option("body"), data...))
|
|
||||||
} else {
|
|
||||||
data := map[string]interface{}{}
|
|
||||||
for i := 1; i < len(arg)-1; i += 2 {
|
|
||||||
switch arg[i+1] {
|
|
||||||
case "false":
|
|
||||||
data[arg[i]] = false
|
|
||||||
case "true":
|
|
||||||
data[arg[i]] = true
|
|
||||||
default:
|
|
||||||
if len(arg[i+1]) > 1 && arg[i+1][0] == '$' {
|
|
||||||
data[arg[i]] = m.Cap(arg[i+1][1:])
|
|
||||||
} else {
|
|
||||||
data[arg[i]] = arg[i+1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b, e := json.Marshal(data)
|
|
||||||
m.Assert(e)
|
|
||||||
body = bytes.NewReader(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
content_type = "application/json"
|
|
||||||
if index > -1 {
|
|
||||||
uri = uri[:index]
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if index > 0 {
|
|
||||||
content_type = "application/x-www-form-urlencoded"
|
|
||||||
body = strings.NewReader(uri[index+1:])
|
|
||||||
uri = uri[:index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req, e := http.NewRequest(method, uri, body)
|
|
||||||
m.Assert(e)
|
|
||||||
for i := 0; i < len(m.Meta["headers"]); i += 2 {
|
|
||||||
req.Header.Set(m.Meta["headers"][i], m.Meta["headers"][i+1])
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(content_type) > 0 {
|
|
||||||
req.Header.Set("Content-Type", content_type)
|
|
||||||
m.Log("info", "content-type: %s", content_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range m.Confv("cookie").(map[string]interface{}) {
|
|
||||||
req.AddCookie(v.(*http.Cookie))
|
|
||||||
}
|
|
||||||
|
|
||||||
res, e := web.Client.Do(req)
|
|
||||||
m.Assert(e)
|
|
||||||
|
|
||||||
for _, v := range res.Cookies() {
|
|
||||||
m.Confv("cookie", v.Name, v)
|
|
||||||
m.Log("info", "set-cookie %s: %v", v.Name, v.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Confs("logheaders") {
|
|
||||||
for k, v := range res.Header {
|
|
||||||
m.Log("info", "%s: %v", k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Confs("output") {
|
|
||||||
if _, e := os.Stat(m.Conf("output")); e == nil {
|
|
||||||
name := path.Join(m.Conf("output"), fmt.Sprintf("%d", time.Now().Unix()))
|
|
||||||
f, e := os.Create(name)
|
|
||||||
m.Assert(e)
|
|
||||||
io.Copy(f, res.Body)
|
|
||||||
if m.Confs("editor") {
|
|
||||||
cmd := exec.Command(m.Conf("editor"), name)
|
|
||||||
cmd.Stdin = os.Stdin
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Run()
|
|
||||||
} else {
|
|
||||||
m.Echo("write to %s\n", name)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf, e := ioutil.ReadAll(res.Body)
|
|
||||||
m.Assert(e)
|
|
||||||
|
|
||||||
ct := res.Header.Get("Content-Type")
|
|
||||||
if len(ct) >= 16 && ct[:16] == "application/json" {
|
|
||||||
var result interface{}
|
|
||||||
json.Unmarshal(buf, &result)
|
|
||||||
m.Option("response_json", result)
|
|
||||||
if m.Has("json_route") {
|
|
||||||
routes := strings.Split(m.Option("json_route"), ".")
|
|
||||||
for _, k := range routes {
|
|
||||||
if len(k) > 0 && k[0] == '$' {
|
|
||||||
k = m.Cap(k[1:])
|
|
||||||
}
|
|
||||||
switch r := result.(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
result = r[k]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fields := map[string]bool{}
|
|
||||||
for _, k := range strings.Split(m.Option("fields"), " ") {
|
|
||||||
if k == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fields[k] = true; len(fields) == 1 {
|
|
||||||
m.Meta["append"] = append(m.Meta["append"], "index")
|
|
||||||
}
|
|
||||||
m.Meta["append"] = append(m.Meta["append"], k)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fields) > 0 {
|
|
||||||
|
|
||||||
switch ret := result.(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
m.Append("index", "0")
|
|
||||||
for k, v := range ret {
|
|
||||||
switch value := v.(type) {
|
|
||||||
case string:
|
|
||||||
m.Append(k, strings.Replace(value, "\n", " ", -1))
|
|
||||||
case float64:
|
|
||||||
m.Append(k, fmt.Sprintf("%d", int(value)))
|
|
||||||
default:
|
|
||||||
if _, ok := fields[k]; ok {
|
|
||||||
m.Append(k, fmt.Sprintf("%v", value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case []interface{}:
|
|
||||||
for i, r := range ret {
|
|
||||||
m.Add("append", "index", i)
|
|
||||||
if rr, ok := r.(map[string]interface{}); ok {
|
|
||||||
for k, v := range rr {
|
|
||||||
switch value := v.(type) {
|
|
||||||
case string:
|
|
||||||
if _, ok := fields[k]; len(fields) == 0 || ok {
|
|
||||||
m.Add("append", k, strings.Replace(value, "\n", " ", -1))
|
|
||||||
}
|
|
||||||
case float64:
|
|
||||||
if _, ok := fields[k]; len(fields) == 0 || ok {
|
|
||||||
m.Add("append", k, fmt.Sprintf("%d", int64(value)))
|
|
||||||
}
|
|
||||||
case bool:
|
|
||||||
if _, ok := fields[k]; len(fields) == 0 || ok {
|
|
||||||
m.Add("append", k, fmt.Sprintf("%v", value))
|
|
||||||
}
|
|
||||||
case map[string]interface{}:
|
|
||||||
for kk, vv := range value {
|
|
||||||
key := k + "." + kk
|
|
||||||
if _, ok := fields[key]; len(fields) == 0 || ok {
|
|
||||||
m.Add("append", key, strings.Replace(fmt.Sprintf("%v", vv), "\n", " ", -1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if _, ok := fields[k]; ok {
|
|
||||||
m.Add("append", k, fmt.Sprintf("%v", value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Has("json_key") {
|
|
||||||
m.Sort(m.Option("json_key"))
|
|
||||||
}
|
|
||||||
m.Meta["index"] = nil
|
|
||||||
for i, _ := range ret {
|
|
||||||
m.Add("append", "index", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Table(); len(m.Meta["append"]) == 0 {
|
|
||||||
m.Echo("%s", string(buf))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
wiki := &WIKI{}
|
wiki := &web.WEB{}
|
||||||
wiki.Context = Index
|
wiki.Context = Index
|
||||||
web.Index.Register(Index, wiki)
|
web.Index.Register(Index, wiki)
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,3 @@
|
|||||||
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 copy_to_clipboard(text) {
|
function copy_to_clipboard(text) {
|
||||||
var clipboard = document.querySelector(".clipboard")
|
var clipboard = document.querySelector(".clipboard")
|
||||||
clipboard.value = text
|
clipboard.value = text
|
@ -126,3 +126,23 @@ context = {
|
|||||||
xhr.send();
|
xhr.send();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.isMobile = navigator.userAgent.indexOf("Mobile") > -1
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
154
usr/librarys/wiki.js
Normal file
154
usr/librarys/wiki.js
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
function action(event, cmd) {
|
||||||
|
switch (cmd) {
|
||||||
|
case "toggle_nav":
|
||||||
|
var nav = document.querySelector("nav")
|
||||||
|
nav.hidden = !nav.hidden
|
||||||
|
var article = document.querySelector("article")
|
||||||
|
if (!context.isMobile) {
|
||||||
|
article.style.width = nav.hidden? "80%": "calc(100% - 250px)"
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "toggle_list":
|
||||||
|
var list = document.querySelector(".list")
|
||||||
|
list.hidden = !list.hidden
|
||||||
|
break
|
||||||
|
case "toggle_menu":
|
||||||
|
var menu = document.querySelector(".menu")
|
||||||
|
menu.hidden = !menu.hidden
|
||||||
|
break
|
||||||
|
case "toggle_link":
|
||||||
|
var link = document.querySelector(".link")
|
||||||
|
link.hidden = !link.hidden
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_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;
|
||||||
|
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 = append_child(m[i], "li")
|
||||||
|
var a = append_child(one, "a")
|
||||||
|
a.href = "#"+list[j].hash;
|
||||||
|
a.innerText = text+" ("+parseInt((list[j].position-min)/max*100)+"%)";
|
||||||
|
|
||||||
|
one.className = list[j].level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_link() {
|
||||||
|
var link = [];
|
||||||
|
var a = document.querySelectorAll(".text a");
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
link.push({href: a[i].href, title: a[i].innerText});
|
||||||
|
}
|
||||||
|
var m = document.getElementsByClassName("link");
|
||||||
|
for (var i = 0; i < m.length; i++) {
|
||||||
|
var one = append_child(m[i], "li")
|
||||||
|
var a = one.appendChild(document.createTextNode("相关链接: "));
|
||||||
|
|
||||||
|
for (var j = 0; j < link.length; j++) {
|
||||||
|
var one = append_child(m[i], "li")
|
||||||
|
var a = one.appendChild(document.createTextNode(link[j].title+": "));
|
||||||
|
var a = append_child(one, "a");
|
||||||
|
a.href = link[j].href
|
||||||
|
a.innerText = a.href
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_code() {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
init_menu()
|
||||||
|
init_link()
|
||||||
|
init_code()
|
||||||
|
var article = document.querySelector("article")
|
||||||
|
var mav = document.querySelector("nav")
|
||||||
|
alert(context.isMobile)
|
||||||
|
if (context.isMobile) {
|
||||||
|
article.style.width = "100%"
|
||||||
|
} else {
|
||||||
|
article.style.maxHeight = "calc(100% - 80px)"
|
||||||
|
mav.style.maxHeight = "calc(100% - 80px)"
|
||||||
|
}
|
||||||
|
}
|
198
usr/template/code/code.tmpl
Normal file
198
usr/template/code/code.tmpl
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
{{define "head"}}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=0.7">
|
||||||
|
<title>{{option .Meta "page_title"}}</title>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
height:100%;
|
||||||
|
width:100%;
|
||||||
|
margin:0px;
|
||||||
|
background-color:#d8d8d8;
|
||||||
|
}
|
||||||
|
fieldset {
|
||||||
|
margin-top:8px;
|
||||||
|
}
|
||||||
|
legend {
|
||||||
|
font-size:16px;
|
||||||
|
font-weight:bold;
|
||||||
|
font-family:monospace;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
textarea.clipboard {
|
||||||
|
color:white;
|
||||||
|
background-color:#272822;
|
||||||
|
width:600px;
|
||||||
|
}
|
||||||
|
form.option div {
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
form.option hr {
|
||||||
|
clear:both;
|
||||||
|
}
|
||||||
|
form.option label.keymap {
|
||||||
|
color:red;
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
form.option label.keymap.show {
|
||||||
|
display:inline;
|
||||||
|
}
|
||||||
|
form.option input {
|
||||||
|
margin-right:10px;
|
||||||
|
}
|
||||||
|
form.option input.cmd {
|
||||||
|
color:white;
|
||||||
|
background-color:#272822;
|
||||||
|
padding-left:10px;
|
||||||
|
width:600px;
|
||||||
|
}
|
||||||
|
form.option.exec input {
|
||||||
|
color:white;
|
||||||
|
background-color:#272822;
|
||||||
|
padding-left:10px;
|
||||||
|
width:600px;
|
||||||
|
}
|
||||||
|
form.option select {
|
||||||
|
margin-right:10px;
|
||||||
|
}
|
||||||
|
table.append {
|
||||||
|
font-size:14px;
|
||||||
|
}
|
||||||
|
table.append th {
|
||||||
|
font-family:monospace;
|
||||||
|
background-color:lightgreen;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
table.append th.order {
|
||||||
|
background-color:red;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
table.append td {
|
||||||
|
font-family:monospace;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
code.result pre {
|
||||||
|
color:white;
|
||||||
|
font-size:14px;
|
||||||
|
background-color:#272822;
|
||||||
|
overflow:scroll;
|
||||||
|
padding:5px;
|
||||||
|
border:solid 2px green;
|
||||||
|
border-left:solid 4px green;
|
||||||
|
margin:0;
|
||||||
|
}
|
||||||
|
code.result pre.clipboard {
|
||||||
|
height:2em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body onkeyup="return onaction(event, 'keymap')">
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "void"}}{{end}}
|
||||||
|
|
||||||
|
{{define "detail"}}{{detail .}}{{end}}
|
||||||
|
{{define "option"}}{{option .}}{{end}}
|
||||||
|
{{define "append"}}{{append .}}{{end}}
|
||||||
|
{{define "result"}}{{result .}}{{end}}
|
||||||
|
|
||||||
|
{{define "clipboard"}}
|
||||||
|
<fieldset><legend>clipboard</legend>
|
||||||
|
<datalist id="clipstack"></datalist>
|
||||||
|
<datalist id="clistack"></datalist>
|
||||||
|
<textarea class="clipboard"></textarea>
|
||||||
|
</fieldset>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "componet"}}
|
||||||
|
<fieldset><legend title="{{option .Meta "help"}}">{{option .Meta "help"}}({{option .Meta "context"}}.{{option .Meta "command"}})</legend>
|
||||||
|
{{$form_type := option . "form_type"|meta}}
|
||||||
|
|
||||||
|
{{if eq $form_type "upload"}}
|
||||||
|
{{end}}
|
||||||
|
<form class="option {{option .Meta "name"}}"
|
||||||
|
data-last_componet_group="{{option . "last_componet_group"|meta}}"
|
||||||
|
data-last_componet_order="{{option . "last_componet_order"|meta}}"
|
||||||
|
data-componet_group="{{option . "componet_group"|meta}}"
|
||||||
|
data-componet_order="{{option . "componet_order"|meta}}"
|
||||||
|
data-componet_name="{{option . "name"|meta}}"
|
||||||
|
data-componet_help="{{option . "help"|meta}}"
|
||||||
|
{{if eq $form_type "upload"}}
|
||||||
|
method="POST" action="/upload" enctype="multipart/form-data"
|
||||||
|
onsubmit="onaction(event,'upload')"
|
||||||
|
{{end}}
|
||||||
|
>
|
||||||
|
<input style="display:none"></input>
|
||||||
|
{{range $index, $input := option . "inputs"}}
|
||||||
|
<div>
|
||||||
|
{{$type := index $input "type"}}
|
||||||
|
{{if index $input "label"}}
|
||||||
|
<label>{{index $input "label"}} : </label>
|
||||||
|
{{end}}
|
||||||
|
{{if eq $type "button"}}
|
||||||
|
<input type="button" onclick="return onaction(event, 'command')" value="{{index $input "label"}}">
|
||||||
|
{{else if eq $type "submit"}}
|
||||||
|
<input type="submit" value="{{index $input "value"}}">
|
||||||
|
{{else if eq $type "file"}}
|
||||||
|
<input type="file" name="{{index $input "name"}}">
|
||||||
|
{{else if eq $type "choice"}}
|
||||||
|
{{$default_value := index $input "value"}}
|
||||||
|
<select name="{{index $input "name"}}" onchange="return onaction(event, 'command')">
|
||||||
|
{{range $index, $value := index $input "choice"}}
|
||||||
|
{{$val := index $value "value"}}
|
||||||
|
{{if eq $default_value $val}}
|
||||||
|
<option value="{{index $value "value"}}" selected>{{index $value "name"}}</option>
|
||||||
|
{{else}}
|
||||||
|
<option value="{{index $value "value"}}">{{index $value "name"}}</option>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
{{else}}
|
||||||
|
<input
|
||||||
|
name="{{index $input "name"}}"
|
||||||
|
value="{{index $input "value"}}"
|
||||||
|
class="{{index $input "class"}}"
|
||||||
|
{{if index $input "clipstack"}}
|
||||||
|
list="{{index $input "clipstack"}}"
|
||||||
|
{{else}}
|
||||||
|
list="clipstack"
|
||||||
|
{{end}}
|
||||||
|
onclick="return onaction(event, 'click')"
|
||||||
|
onkeyup="return onaction(event, 'input')">
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
<hr/>
|
||||||
|
</form>
|
||||||
|
{{if eq $form_type "upload"}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if index .Meta "display_append"}}
|
||||||
|
{{option .Meta "display_append"}}
|
||||||
|
{{else}}
|
||||||
|
<table class="append {{option .Meta "name"}}">
|
||||||
|
{{$msg := .}}
|
||||||
|
<tr>{{range $field := append .}}<th>{{$field}}</th>{{end}}</tr>
|
||||||
|
{{range $line := table .}}
|
||||||
|
<tr>{{range $field := append $msg}}<td>{{index $line $field|unescape}}</td>{{end}}</tr>
|
||||||
|
{{end}}
|
||||||
|
</table>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if index .Meta "display_result"}}
|
||||||
|
{{option .Meta "display_result"}}
|
||||||
|
{{else}}
|
||||||
|
<code class="result {{option .Meta "name"}}"><pre>{{result .Meta}}</pre></code>
|
||||||
|
{{end}}
|
||||||
|
</fieldset>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "tail"}}
|
||||||
|
<script src="/librarys/context.js"></script>
|
||||||
|
<script src="/librarys/code.js"></script>
|
||||||
|
</body>
|
||||||
|
{{end}}
|
148
usr/template/wiki/wiki.tmpl
Normal file
148
usr/template/wiki/wiki.tmpl
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
{{define "head"}}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=0.7">
|
||||||
|
<title>{{option .Meta "page_title"}}</title>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
height:100%;
|
||||||
|
width:100%;
|
||||||
|
margin:0px;
|
||||||
|
background-color:#d8d8d8;
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
color:white;
|
||||||
|
font-size:20px;
|
||||||
|
font-family:monospace;
|
||||||
|
text-align:center;
|
||||||
|
background-color:#0747a6;
|
||||||
|
width:100%;
|
||||||
|
height:40px;
|
||||||
|
}
|
||||||
|
header .title {
|
||||||
|
padding:6px;
|
||||||
|
}
|
||||||
|
header .toggle {
|
||||||
|
cursor:pointer;
|
||||||
|
width:40px;
|
||||||
|
position:absolute;
|
||||||
|
left:20px;
|
||||||
|
top:5px;
|
||||||
|
}
|
||||||
|
header .toggle:hover {
|
||||||
|
background-color:blue;
|
||||||
|
}
|
||||||
|
header .search {
|
||||||
|
position:absolute;
|
||||||
|
right:20px;
|
||||||
|
top:5px;
|
||||||
|
}
|
||||||
|
header .search input {
|
||||||
|
font-size:14px;
|
||||||
|
background-color:#91d7f5;
|
||||||
|
padding:4px;
|
||||||
|
width:60px;
|
||||||
|
}
|
||||||
|
header .search input:focus {
|
||||||
|
width:120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
float:left;
|
||||||
|
min-width:250px;
|
||||||
|
overflow:auto;
|
||||||
|
}
|
||||||
|
article {
|
||||||
|
float:left;
|
||||||
|
width:calc(100% - 250px);
|
||||||
|
min-width:600px;
|
||||||
|
overflow:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list li {
|
||||||
|
padding-top:10px;
|
||||||
|
}
|
||||||
|
.list li:hover {
|
||||||
|
background-color:green;
|
||||||
|
}
|
||||||
|
.list a {
|
||||||
|
text-decoration-line:none;
|
||||||
|
}
|
||||||
|
.toggle_menu {
|
||||||
|
width:100%;
|
||||||
|
cursor:pointer;
|
||||||
|
background-color:green;
|
||||||
|
}
|
||||||
|
.menu li {
|
||||||
|
padding-top:10px;
|
||||||
|
}
|
||||||
|
.menu a {
|
||||||
|
text-decoration-line:none;
|
||||||
|
}
|
||||||
|
.menu li:hover {
|
||||||
|
background-color:green;
|
||||||
|
}
|
||||||
|
.toggle_list {
|
||||||
|
width:100%;
|
||||||
|
cursor:pointer;
|
||||||
|
background-color:green;
|
||||||
|
}
|
||||||
|
.link a {
|
||||||
|
text-decoration-line:none;
|
||||||
|
}
|
||||||
|
.text {
|
||||||
|
margin:20px;
|
||||||
|
}
|
||||||
|
.mono {
|
||||||
|
font-family:monospace;
|
||||||
|
}
|
||||||
|
footer {
|
||||||
|
clear:both;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "header"}}
|
||||||
|
<header>
|
||||||
|
<div class="toggle" onclick="action(event, 'toggle_nav')">三</div>
|
||||||
|
<div class="search"><input type="text" placeholder="搜索"></div>
|
||||||
|
<div class="title">shylinux</div>
|
||||||
|
</header>
|
||||||
|
<nav>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "list"}}
|
||||||
|
<div class="toggle_menu" onclick="action(event, 'toggle_list')">文章</div>
|
||||||
|
<ul class="list" hidden>
|
||||||
|
{{range $i, $l := table .}}
|
||||||
|
<li>
|
||||||
|
<a href="?wiki_favor={{index $l "file"}}">{{index $l "file"}}</a><br/>
|
||||||
|
<span class="mono"> {{index $l "time"}} </span>
|
||||||
|
</li>
|
||||||
|
{{end}}
|
||||||
|
</ul>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "text"}}
|
||||||
|
<div class="toggle_menu" onclick="action(event, 'toggle_menu')">目录</div>
|
||||||
|
<ul class="menu"></ul>
|
||||||
|
</nav>
|
||||||
|
<article>
|
||||||
|
<div class="toggle_link" onclick="action(event, 'toggle_link')">参考链接</div>
|
||||||
|
<ul class="link" hidden></ul>
|
||||||
|
<div class="text">{{result .|meta|unescape}}</div>
|
||||||
|
</article>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "footer"}}
|
||||||
|
<footer>shylinux</footer>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "tail"}}
|
||||||
|
<script src="/librarys/context.js"></script>
|
||||||
|
<script src="/librarys/wiki.js"></script>
|
||||||
|
</body>
|
||||||
|
{{end}}
|
Loading…
x
Reference in New Issue
Block a user