1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-25 16:58:06 +08:00
Change-Id: Iff5cd740dadbb763dd3e02b1b3849065d67a6598
This commit is contained in:
shaoying 2018-12-14 00:32:06 +08:00
parent d87448ade9
commit 60901ac971
8 changed files with 368 additions and 199 deletions

View File

@ -23,7 +23,9 @@ install_all: install
run:
etc/bootstrap.sh
shy:
cp -r src/toolkit ~/context/src/
cp -r src/contexts ~/context/src/
cp -r src/examples ~/context/src/
cp -r usr/template ~/context/usr/
cp -r usr/librarys/ ~/context/usr/

View File

@ -2042,15 +2042,7 @@ var CGI = template.FuncMap{
return ""
}
if m, ok := arg[0].(*Message); ok {
if len(arg) == 1 {
return fmt.Sprintf("%v", m)
}
msg := m.Spawn(m.Target()).Cmd(arg[1:]...)
return strings.Join(msg.Meta["result"], "")
}
return ""
return strings.Join(Pulse.Sess("cli").Cmd(arg).Meta["result"], "")
},
"detail": func(arg ...interface{}) interface{} {
@ -2254,33 +2246,6 @@ var CGI = template.FuncMap{
return []interface{}{}
},
"slice": func(list interface{}, arg ...interface{}) interface{} {
switch l := list.(type) {
case string:
if len(arg) == 0 {
return l
}
if len(arg) == 1 {
return l[arg[0].(int):]
}
if len(arg) == 2 {
return l[arg[0].(int):arg[1].(int)]
}
}
return ""
},
"unescape": func(str string) interface{} {
return template.HTML(str)
},
"json": func(arg ...interface{}) interface{} {
if len(arg) == 0 {
return ""
}
b, _ := json.Marshal(arg[0])
return string(b)
},
"list": func(arg interface{}) interface{} {
n := 0
switch v := arg.(type) {
@ -2299,6 +2264,80 @@ var CGI = template.FuncMap{
}
return list
},
"slice": func(list interface{}, arg ...interface{}) interface{} {
switch l := list.(type) {
case string:
if len(arg) == 0 {
return l
}
if len(arg) == 1 {
return l[arg[0].(int):]
}
if len(arg) == 2 {
return l[arg[0].(int):arg[1].(int)]
}
}
return ""
},
"unescape": func(str string) interface{} {
return template.HTML(str)
},
"json": func(arg ...interface{}) interface{} {
if len(arg) == 0 {
return ""
}
b, _ := json.Marshal(arg[0])
return string(b)
},
"so": func(arg ...interface{}) interface{} {
if len(arg) == 0 {
return ""
}
cli := Pulse.Sess("cli")
cli.Cmd("source", strings.Join(Trans(arg), " "))
result := []string{}
if len(cli.Meta["append"]) > 0 {
result = append(result, "<table>")
result = append(result, "<caption>")
result = append(result, Trans(arg)...)
result = append(result, "</caption>")
cli.Table(func(maps map[string]string, list []string, line int) bool {
if line == -1 {
result = append(result, "<tr>")
for _, v := range list {
result = append(result, "<th>")
result = append(result, v)
result = append(result, "</th>")
}
result = append(result, "</tr>")
return true
}
result = append(result, "<tr>")
for _, v := range list {
result = append(result, "<td>")
result = append(result, v)
result = append(result, "</td>")
}
result = append(result, "</tr>")
return true
})
result = append(result, "</table>")
} else {
result = append(result, "<pre><code>")
result = append(result, fmt.Sprintf("%s", cli.Find("shy", false).Conf("prompt")))
result = append(result, Trans(arg)...)
result = append(result, "\n")
result = append(result, cli.Meta["result"]...)
result = append(result, "</code></pre>")
}
return template.HTML(strings.Join(result, ""))
},
}
var Pulse = &Message{code: 0, time: time.Now(), source: Index, target: Index, Meta: map[string][]string{}}
var Index = &Context{Name: "ctx", Help: "模块中心",

View File

@ -94,6 +94,8 @@ 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("index_path", r.Header.Get("index_path"))
msg.Option("index_url", r.Header.Get("index_url"))
msg.Option("remote_addr", r.RemoteAddr)
msg.Option("dir_root", m.Cap("directory"))
msg.Option("referer", r.Header.Get("Referer"))
@ -112,16 +114,20 @@ func (web *WEB) HandleCmd(m *ctx.Message, key string, cmd *ctx.Command) {
for k, v := range r.Form {
msg.Add("option", k, v)
if k == "ticket" {
m.Log("info", "hide ticket %v %v %v %v", k, v, r.URL, r.Header.Get("index_path"))
uri, _ := r.URL.Parse(r.Header.Get("index_path"))
http.Redirect(w, r, uri.Path+"?bench="+uri.Query().Get("bench"), http.StatusTemporaryRedirect)
m.Log("info", "hide ticket %v %v %v", k, v, msg.Option("index_url"))
uri, _ := r.URL.Parse(r.Header.Get("index_url"))
redirect := uri.Path
if b := uri.Query().Get("bench"); b != "" {
redirect += "?bench=" + b
}
http.Redirect(w, r, redirect, http.StatusTemporaryRedirect)
return
}
}
if msg.Confs("cas_url") {
if !cas.IsAuthenticated(r) && !msg.Confs("skip_cas") {
r.URL, _ = r.URL.Parse(r.Header.Get("index_path"))
r.URL, _ = r.URL.Parse(r.Header.Get("index_url"))
cas.RedirectToLogin(w, r)
return
}
@ -181,7 +187,8 @@ func (web *WEB) ServeHTTP(w http.ResponseWriter, r *http.Request) {
r.Header.Set("index_module", m.Cap("module"))
if index {
r.Header.Set("index_path", r.URL.String())
r.Header.Set("index_url", r.URL.String())
r.Header.Set("index_path", r.URL.Path)
m.Log("info", "").Log("info", "%v %s %s", r.RemoteAddr, r.Method, r.URL)
}
@ -351,7 +358,8 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
},
}, Help: "组件列表"},
"bench": &ctx.Config{Name: "bench", Value: map[string]interface{}{}, Help: "工作流"},
"bench_disable": &ctx.Config{Name: "bench_disable", Value: "false", Help: "工作流"},
"bench": &ctx.Config{Name: "bench", Value: map[string]interface{}{}, Help: "工作流"},
"bench_view": &ctx.Config{Name: "bench_view", Value: map[string]interface{}{
"base": []interface{}{"key", "share", "comment", "creator", "create_time", "modify_time", "commands"},
"link": []interface{}{"share", "comment", "creator", "link"},
@ -422,7 +430,13 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
arg[0] = fmt.Sprintf(arg[0], values...)
}
method := m.Confx("method")
method := m.Conf("method")
if m.Has("method") {
method = m.Option("method")
}
m.Log("fuck", "what %s", method)
m.Log("fuck", "what %s", m.Option("method"))
m.Log("fuck", "what %s", m.Conf("method"))
uri := Merge(m, arg[0], arg[1:]...)
body, _ := m.Optionv("body").(io.Reader)
@ -432,6 +446,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
}
}
m.Log("fuck", "what %s", method)
req, e := http.NewRequest(method, uri, body)
m.Assert(e)
@ -999,9 +1014,9 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
}
bench_share := ""
if right {
if right && !m.Confs("bench_disable") {
if _, ok := m.Confv("bench", m.Option("bench")).(map[string]interface{}); !ok { // 创建工作流
m.Append("redirect", fmt.Sprintf("?bench=%s", m.Spawn().Cmd("bench", "create").Append("key")))
m.Append("redirect", fmt.Sprintf("%s?bench=%s", m.Option("index_path"), m.Spawn().Cmd("bench", "create").Append("key")))
return
}
if bench_share = m.Spawn().Cmd("bench", "check", m.Option("username")).Result(0); bench_share == "private" {

View File

@ -8,6 +8,7 @@ import (
"encoding/xml"
"fmt"
"github.com/gomarkdown/markdown"
"html/template"
"io/ioutil"
"net/http"
"os"
@ -26,21 +27,22 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心",
"md": true,
}, Help: "路由数量"},
"bench_disable": &ctx.Config{Name: "bench_disable", Value: "true", 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"},
map[string]interface{}{"componet_name": "head", "template": "head"},
map[string]interface{}{"componet_name": "header", "template": "header"},
map[string]interface{}{"componet_name": "list", "template": "list",
"componet_ctx": "web.wiki", "componet_cmd": "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"},
map[string]interface{}{"componet_name": "text", "template": "text",
"componet_ctx": "web.wiki", "componet_cmd": "wiki_body", "arguments": []interface{}{"@wiki_favor"},
"pre_run": true,
},
map[string]interface{}{"name": "footer", "template": "footer"},
map[string]interface{}{"name": "tail", "template": "tail"},
map[string]interface{}{"componet_name": "footer", "template": "footer"},
map[string]interface{}{"componet_name": "tail", "template": "tail"},
},
}, Help: "组件列表"},
},
@ -109,6 +111,15 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心",
"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 {
buffer := bytes.NewBuffer([]byte{})
temp, e := template.New("temp").Funcs(ctx.CGI).Parse(string(ls))
if e != nil {
m.Log("info", "parse %s %s", which, e)
}
temp.Execute(buffer, m)
ls = buffer.Bytes()
ls = markdown.ToHTML(ls, nil, nil)
m.Echo(string(ls))
}
@ -216,11 +227,11 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心",
}
ls = markdown.ToHTML(ls, nil, nil)
default:
pre = true
}
}
if pre {
m.Option("nline", bytes.Count(ls, []byte("\n")))
m.Option("nbyte", len(ls))

View File

@ -274,73 +274,6 @@ function get_history(input, index, cmd) {
return cmd
}
function sort_table(table, index, sort_asc) {
var list = table.querySelectorAll("tr")
var new_list = []
var is_time = true
var is_number = true
for (var i = 1; i < list.length; i++) {
var value = Date.parse(list[i].childNodes[index].innerText)
if (!(value > 0)) {
is_time = false
}
var value = parseInt(list[i].childNodes[index].innerText)
if (!(value >= 0 || value <= 0)) {
is_number = false
}
new_list.push(list[i])
}
var sort_order = ""
if (is_time) {
if (sort_asc) {
method = function(a, b) {return Date.parse(a) > Date.parse(b)}
sort_order = "time"
} else {
method = function(a, b) {return Date.parse(a) < Date.parse(b)}
sort_order = "time_r"
}
} else if (is_number) {
if (sort_asc) {
method = function(a, b) {return parseInt(a) > parseInt(b)}
sort_order = "int"
} else {
method = function(a, b) {return parseInt(a) < parseInt(b)}
sort_order = "int_r"
}
} else {
if (sort_asc) {
method = function(a, b) {return a > b}
sort_order = "str"
} else {
method = function(a, b) {return a < b}
sort_order = "str_r"
}
}
list = new_list
new_list = []
for (var i = 0; i < list.length; i++) {
list[i].parentElement && list[i].parentElement.removeChild(list[i])
for (var j = i+1; j < list.length; j++) {
if (typeof method == "function" && method(list[i].childNodes[index].innerText, list[j].childNodes[index].innerText)) {
var temp = list[i]
list[i] = list[j]
list[j] = temp
}
}
new_list.push(list[i])
}
for (var i = 0; i < new_list.length; i++) {
table.appendChild(new_list[i])
}
return sort_order
}
function onaction(event, action, arg) {
var target = event.target
var dataset = target.dataset

View File

@ -211,3 +211,70 @@ function format_date(arg) {
return arg.getFullYear()+"-"+month+"-"+date+" "+hour+":"+minute+":"+second
}
function sort_table(table, index, sort_asc) {
var list = table.querySelectorAll("tr")
var new_list = []
var is_time = true
var is_number = true
for (var i = 1; i < list.length; i++) {
var value = Date.parse(list[i].childNodes[index].innerText)
if (!(value > 0)) {
is_time = false
}
var value = parseInt(list[i].childNodes[index].innerText)
if (!(value >= 0 || value <= 0)) {
is_number = false
}
new_list.push(list[i])
}
var sort_order = ""
if (is_time) {
if (sort_asc) {
method = function(a, b) {return Date.parse(a) > Date.parse(b)}
sort_order = "time"
} else {
method = function(a, b) {return Date.parse(a) < Date.parse(b)}
sort_order = "time_r"
}
} else if (is_number) {
if (sort_asc) {
method = function(a, b) {return parseInt(a) > parseInt(b)}
sort_order = "int"
} else {
method = function(a, b) {return parseInt(a) < parseInt(b)}
sort_order = "int_r"
}
} else {
if (sort_asc) {
method = function(a, b) {return a > b}
sort_order = "str"
} else {
method = function(a, b) {return a < b}
sort_order = "str_r"
}
}
list = new_list
new_list = []
for (var i = 0; i < list.length; i++) {
list[i].parentElement && list[i].parentElement.removeChild(list[i])
for (var j = i+1; j < list.length; j++) {
if (typeof method == "function" && method(list[i].childNodes[index].innerText, list[j].childNodes[index].innerText)) {
var temp = list[i]
list[i] = list[j]
list[j] = temp
}
}
new_list.push(list[i])
}
for (var i = 0; i < new_list.length; i++) {
table.appendChild(new_list[i])
}
return sort_order
}

View File

@ -3,10 +3,7 @@ function action(event, 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% - 400px)"
}
set_layout(event)
break
case "toggle_list":
var list = document.querySelector(".list")
@ -31,8 +28,10 @@ function init_menu() {
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) {}
head[j].id = hs[i]+"_"+j
head[j].onclick = function(event) {
location.hash=event.target.id
}
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;
@ -120,35 +119,72 @@ function init_link() {
}
function init_code() {
var fuck = context.isMobile? 22: 16
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"
var nu = insert_before(m[i], "div", {"className": "number1"})
var line = (m[i].clientHeight-10)/fuck
for (var j = 1; j <= line; j++) {
console.log(j)
var li = nu.appendChild(document.createElement("div"));
li.appendChild(document.createTextNode(""+j));
append_child(nu, "div", {
"style": {
"fontSize": context.isMobile?"20px":"14px",
"lineHeight": context.isMobile?"22px":"16px",
},
"id": "code"+i+"_"+"line"+j,
"onclick": function(event) {
location.href = "#"+event.target.id
},
}).appendChild(document.createTextNode(""+j));
}
}
}
function add_sort(append, field, cb) {
append.onclick = function(event) {
var target = event.target
var dataset = target.dataset
var nodes = target.parentElement.childNodes
for (var i = 0; i < nodes.length; i++) {
if (nodes[i] == target) {
if (target.tagName == "TH") {
dataset["sort_asc"] = (dataset["sort_asc"] == "1") ? 0: 1
sort_table(append, i, dataset["sort_asc"] == "1")
} else if (target.tagName == "TD") {
var tr = target.parentElement.parentElement.querySelector("tr")
if (tr.childNodes[i].innerText.startsWith(field)) {
typeof cb == "function" && cb(event)
}
}
}
}
}
}
function init_table(event) {
var append = document.querySelectorAll("article table").forEach(add_sort)
}
function set_layout() {
article = document.querySelector("article")
nav = document.querySelector("nav")
if (window.innerWidth > 600) {
article.style.maxWidth = (window.innerWidth - nav.offsetWidth-40)+"px"
nav.className = "fixed"
} else {
article.style.maxWidth = ""
nav.className = ""
}
}
window.onresize = function (event) {
set_layout()
}
window.onload = function() {
init_menu()
init_link()
init_code()
var article = document.querySelector("article")
var nav = document.querySelector("nav")
if (context.isMobile) {
article.style.width = "100%"
} else {
article.style.maxHeight = "calc(100% - 80px)"
nav.style.maxHeight = "calc(100% - 80px)"
}
article.style.width = nav.hidden? "80%": "calc(100% - 400px)"
init_table()
set_layout()
}

View File

@ -19,6 +19,7 @@ header {
background-color:#0747a6;
width:100%;
height:40px;
position:fixed;
}
header .title {
padding:6px;
@ -49,55 +50,117 @@ header .search input:focus {
}
nav {
min-width:240px;
margin-top:40px;
float:left;
min-width:250px;
}
nav.fixed {
overflow:auto;
max-height:calc(100% - 40px);
position:fixed;
}
article {
float:left;
width:calc(100% - 400px);
min-width:400px;
overflow:auto;
nav>ul {
padding:0;
margin:0;
}
.list li {
padding-top:10px;
}
.list li:hover {
background-color:green;
}
.list a {
text-decoration-line:none;
}
.toggle_menu {
width:100%;
nav>ul>li>div {
cursor:pointer;
font-size:18px;
background-color:green;
}
.menu li {
padding-top:10px;
}
.menu a {
text-decoration-line:none;
}
.menu li:hover {
background-color:green;
}
.toggle_list {
padding-left:10px;
padding:5px;
width:100%;
cursor:pointer;
}
nav>ul>li>ul>li {
padding:5px;
}
nav>ul>li>ul>li:hover {
background-color:green;
}
.link a {
nav>ul>li>ul>li>a {
text-decoration-line:none;
}
.text {
margin:20px;
}
.mono {
font-family:monospace;
}
article {
padding:20px;
max-width:calc(100% - 40px);
float:right;
}
article h2 {
cursor:alias;
}
article h3 {
cursor:alias;
}
article h4 {
cursor:alias;
}
article table {
border-collapse:collapse;
}
article table caption {
font-weight:bold;
border:2px solid green;
}
article table tr:hover {
background:lightgreen;
}
article table th {
background:lightgreen;
border:2px solid green;
text-align:center;
padding:0;
}
article table th:hover {
background-color:red;
cursor:pointer;
}
article table td {
border:2px solid green;
text-align:center;
padding:3px;
}
article table td:hover {
background-color:red;
}
article pre {
color:white;
background-color:#272822;
overflow:scroll;
padding:5px;
border:solid 2px green;
border-left:solid 4px green;
margin:0;
font-size:14px;
line-height:16px;
}
article div.number1 {
color:#ff9800;
font-family:monospace;
background-color:#272822;
text-align:right;
padding:5px 0;
border:solid green 2px;
float:left;
}
article div.number1 div {
padding: 0 5px;
}
article div.number1 div:hover {
cursor:alias;
background-color:red;
}
footer {
height:40px;
background-color:red;
text-align:center;
vertical-align:middle;
clear:both;
}
</style>
@ -111,34 +174,37 @@ footer {
<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>
<nav>
<ul>
<li><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>
</li>
<li><div class="toggle_menu" onclick="action(event, 'toggle_menu')">目录</div>
<ul class="menu"></ul>
</li>
<li><div class="toggle_link" onclick="action(event, 'toggle_link')">参考链接</div>
<ul class="link" hidden></ul>
</li>
</ul>
</nav>
{{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>
<article>{{result .|meta|unescape}}</article>
{{end}}
{{define "footer"}}
<footer>shylinux</footer>
<footer><div>shylinux</div></footer>
{{end}}
{{define "tail"}}