efront 4.4.14 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/#/345/233/275/351/231/205/345/214/226.yml +53 -5
- package/apps/pivot/api.yml +3 -0
- package/apps/pivot/cert/main.xht +181 -0
- package/apps/pivot/cert/orders.xht +144 -0
- package/apps/pivot/menu.yml +1 -0
- package/coms/basic/assert.js +40 -16
- package/coms/basic/cross_.js +20 -3
- package/coms/basic/renderTags.js +23 -0
- package/coms/basic/shallowClone.js +8 -0
- package/coms/basic/shallowEqual.js +13 -4
- package/coms/basic/valid.js +15 -2
- package/coms/compile//347/264/240/351/246/250.js +2 -1
- package/coms/docs/codetext.xht +3 -3
- package/coms/frame/chat.js +1 -1
- package/coms/kugou/bindScroll.js +1 -1
- package/coms/kugou/krc.js +2 -2
- package/coms/layer/leftCenter.js +5 -5
- package/coms/pivot/acme2.js +185 -0
- package/coms/reptile/colored_console.js +5 -17
- package/coms/zimoli/appendChild.js +3 -2
- package/coms/zimoli/autofocus.js +2 -2
- package/coms/zimoli/button.less +4 -3
- package/coms/zimoli/checker.js +34 -15
- package/coms/zimoli/checker.less +2 -3
- package/coms/zimoli/container.js +20 -16
- package/coms/zimoli/data.js +64 -46
- package/coms/zimoli/field.js +3 -3
- package/coms/zimoli/field.less +8 -2
- package/coms/zimoli/filterTime.js +39 -8
- package/coms/zimoli/fromBase64.js +2 -0
- package/coms/zimoli/grid.js +2 -2
- package/coms/zimoli/isMounted.js +3 -3
- package/coms/zimoli/list.js +3 -3
- package/coms/zimoli/maps.js +1 -1
- package/coms/zimoli/menuList.js +1 -1
- package/coms/zimoli/model.js +41 -5
- package/coms/zimoli/on.js +4 -4
- package/coms/zimoli/remove.js +3 -3
- package/coms/zimoli/render.js +25 -33
- package/coms/zimoli/scrollbar.js +52 -19
- package/coms/zimoli/scrollbar.less +14 -2
- package/coms/zimoli/scrollbar_test.less +1 -0
- package/coms/zimoli/select.js +3 -3
- package/coms/zimoli/table.js +1 -1
- package/coms/zimoli/toBase64.js +16 -6
- package/coms/zimoli/view.js +19 -12
- package/coms/zimoli/view.less +5 -3
- package/docs/loader.js +1 -1
- package/package.json +1 -1
- package/public/efront.js +1 -1
|
@@ -1,3 +1,51 @@
|
|
|
1
|
+
- zh-CN: 请求无效!
|
|
2
|
+
en: Request is invalid!
|
|
3
|
+
|
|
4
|
+
- zh-CN: 已取消
|
|
5
|
+
en: Canceled
|
|
6
|
+
|
|
7
|
+
- zh-CN: 输入原密码:
|
|
8
|
+
en: "Enter the original password:"
|
|
9
|
+
|
|
10
|
+
- zh-CN: 数据过载..
|
|
11
|
+
en: Data overload..
|
|
12
|
+
|
|
13
|
+
- zh-CN: 服务器忙!
|
|
14
|
+
en: Server busy!
|
|
15
|
+
|
|
16
|
+
- zh-CN: 无权访问
|
|
17
|
+
en: Unauthorized access
|
|
18
|
+
|
|
19
|
+
- zh-CN: 清理完成
|
|
20
|
+
en: Cleaning completed
|
|
21
|
+
|
|
22
|
+
- zh-CN: 正在重启
|
|
23
|
+
en: Restarting
|
|
24
|
+
|
|
25
|
+
- zh-CN: 已存在相同标识的数据
|
|
26
|
+
en: Data with the same identifier already exists
|
|
27
|
+
|
|
28
|
+
- zh-CN: 禁止访问
|
|
29
|
+
en: Prohibit access
|
|
30
|
+
|
|
31
|
+
- zh-CN: 已关闭$1端口
|
|
32
|
+
en: $1 port has been closed
|
|
33
|
+
|
|
34
|
+
- zh-CN: <red>端口异常</red>
|
|
35
|
+
en: <red>Port exception</red>
|
|
36
|
+
|
|
37
|
+
- zh-CN: filelist
|
|
38
|
+
en: filelist
|
|
39
|
+
|
|
40
|
+
- zh-CN: pathlist
|
|
41
|
+
en: pathlist
|
|
42
|
+
|
|
43
|
+
- zh-CN: pathend
|
|
44
|
+
en: pathend
|
|
45
|
+
|
|
46
|
+
- zh-CN: 邮箱
|
|
47
|
+
en: mailbox
|
|
48
|
+
|
|
1
49
|
- zh-CN: 过滤空串
|
|
2
50
|
en: Filter empty strings
|
|
3
51
|
|
|
@@ -5,10 +53,10 @@
|
|
|
5
53
|
en: ","
|
|
6
54
|
|
|
7
55
|
- zh-CN: ,
|
|
8
|
-
en:
|
|
56
|
+
en: .
|
|
9
57
|
|
|
10
58
|
- zh-CN: !
|
|
11
|
-
en:
|
|
59
|
+
en: !
|
|
12
60
|
|
|
13
61
|
- zh-CN: https://letsencrypt.org/zh-cn/
|
|
14
62
|
en:
|
|
@@ -260,7 +308,7 @@
|
|
|
260
308
|
en: Server restart
|
|
261
309
|
|
|
262
310
|
- zh-CN: 正在退出..
|
|
263
|
-
en: Exiting
|
|
311
|
+
en: Exiting..
|
|
264
312
|
|
|
265
313
|
- zh-CN: 进程已退出
|
|
266
314
|
en: Process has exited
|
|
@@ -401,7 +449,7 @@
|
|
|
401
449
|
en: Not supported
|
|
402
450
|
|
|
403
451
|
- zh-CN: 当前运行环境使用class extends Array会有难以解决的不兼容性问题,请更换代码的实现方式!
|
|
404
|
-
en:
|
|
452
|
+
en: The current operating environment using class extends Array may have compatibility issues that are difficult to solve. Please change the implementation method of the code!
|
|
405
453
|
|
|
406
454
|
- zh-CN: 代码异常!
|
|
407
455
|
en: Code exception!
|
|
@@ -719,7 +767,7 @@
|
|
|
719
767
|
en: The path does not point to file $1
|
|
720
768
|
|
|
721
769
|
- zh-CN: 文件过大!$1
|
|
722
|
-
en: The file is too large$
|
|
770
|
+
en: The file is too large! $1
|
|
723
771
|
|
|
724
772
|
- zh-CN: 读取文件信息出错$1
|
|
725
773
|
en: Error reading file information $1
|
package/apps/pivot/api.yml
CHANGED
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
room: options ::link-:id
|
|
19
19
|
care: options ::care-:id
|
|
20
20
|
cast: options ::cast-:id?:msg
|
|
21
|
+
setauth|: options ::setauth-/.well-known/acme-challenge/:token?:token.:thumb
|
|
22
|
+
unique: options ::unique
|
|
23
|
+
unique-save: options ::unique-:data
|
|
21
24
|
upload: put :path
|
|
22
25
|
https://www.ip.cn/:
|
|
23
26
|
iplocation: get https://www.ip.cn/api/index?ip=:ip&type=1
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
a {
|
|
3
|
+
text-decoration: none;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
* {
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
form {
|
|
12
|
+
display: block;
|
|
13
|
+
max-height: 100%;
|
|
14
|
+
width: 100%;
|
|
15
|
+
|
|
16
|
+
>[body] {
|
|
17
|
+
height: auto;
|
|
18
|
+
height: 100%;
|
|
19
|
+
overflow-x: hidden;
|
|
20
|
+
overflow-y: scroll;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:root {
|
|
25
|
+
height: 100%;
|
|
26
|
+
overflow: auto;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
[type=function] {
|
|
30
|
+
display: -webkit-box;
|
|
31
|
+
-webkit-box-orient: vertical;
|
|
32
|
+
-webkit-line-clamp: 2;
|
|
33
|
+
text-overflow: ellipsis;
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
[info] {
|
|
38
|
+
text-align: center;
|
|
39
|
+
background: #ffe;
|
|
40
|
+
padding: 2px 20px;
|
|
41
|
+
font-size: 14px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
[body] {
|
|
45
|
+
appearance: none;
|
|
46
|
+
border: none;
|
|
47
|
+
}
|
|
48
|
+
</style>
|
|
49
|
+
<div -if="!enabled">
|
|
50
|
+
请在支持window.crypto.subtle的浏览器上使用此页面的功能
|
|
51
|
+
</div>
|
|
52
|
+
<form on-submit="nosubmit" #box>
|
|
53
|
+
<xmenu head #menubar -src="(m,i) in menus" @active="activeMenu(m,i)"></xmenu>
|
|
54
|
+
<div body #body>
|
|
55
|
+
<div info>${i18n`本页使用的证书服务来自`}<a target="_blank" href="${i18n`https://letsencrypt.org/zh-cn/`}">Let's
|
|
56
|
+
Encrypt</a>
|
|
57
|
+
</div>
|
|
58
|
+
<field -repeat="s in actived.fields" -src="[s,formdata]"></field>
|
|
59
|
+
<container -if="actived.src" _src="actived.src" _params="actived.params">
|
|
60
|
+
</container>
|
|
61
|
+
</div>
|
|
62
|
+
<scrollbar y #bar></scrollbar>
|
|
63
|
+
<div foot>
|
|
64
|
+
<span -bind="actived.message"></span>
|
|
65
|
+
<button -repeat="(f,k) in actived.actions" -click="f(actived)"><span -bind="k"></span></button>
|
|
66
|
+
</div>
|
|
67
|
+
</form>
|
|
68
|
+
<script>
|
|
69
|
+
var subtle = window.crypto?.subtle;
|
|
70
|
+
var enabled = acme2.enabled;
|
|
71
|
+
if (!enabled) return;
|
|
72
|
+
var form = view;
|
|
73
|
+
var activeIndex = 0;
|
|
74
|
+
var nosubmit = e => e.preventDefault();
|
|
75
|
+
var directory;
|
|
76
|
+
var formdata = {};
|
|
77
|
+
var private_key, public_key;
|
|
78
|
+
var unique;
|
|
79
|
+
var loadUnique = async function () {
|
|
80
|
+
unique = await data.from("unique");
|
|
81
|
+
await acme2.makeUnique(unique);
|
|
82
|
+
if (acme2.orders?.length) activeMenu(menus[2], 2);
|
|
83
|
+
else if (acme2.kid) activeMenu(menus[1], 1);
|
|
84
|
+
extend(formdata, acme2);
|
|
85
|
+
};
|
|
86
|
+
var publicKey, privateKey;
|
|
87
|
+
loadUnique().then(render.digest).then(lazy(function () {
|
|
88
|
+
box.reshape();
|
|
89
|
+
bar.reshape();
|
|
90
|
+
}));
|
|
91
|
+
var a = button;
|
|
92
|
+
var xmenu = menu;
|
|
93
|
+
var that = this;
|
|
94
|
+
|
|
95
|
+
var saveUnique = async function (params) {
|
|
96
|
+
extendIfOccurs(acme2, params);
|
|
97
|
+
var extra = acme2.pickUnique();
|
|
98
|
+
await data.from("unique-save", { data: extra });
|
|
99
|
+
};
|
|
100
|
+
var openOrder = async function (event, href) {
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
}
|
|
103
|
+
var menus = [
|
|
104
|
+
{
|
|
105
|
+
"name": "创建账户",
|
|
106
|
+
fields: refilm`
|
|
107
|
+
$公钥/public_key/单击生成 ${function (elem) {
|
|
108
|
+
var { data, field } = elem;
|
|
109
|
+
elem.innerHTML = `<a @click="gen()" -if="!data[field.key]">单击生成</a><span -else -bind="data[field.key]"></span>`;
|
|
110
|
+
render(elem, {
|
|
111
|
+
data, field, async gen() {
|
|
112
|
+
await acme2.initUnique();
|
|
113
|
+
formdata.public_key = acme2.public_key;
|
|
114
|
+
await saveUnique();
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
}}
|
|
118
|
+
*邮箱/email email
|
|
119
|
+
/termsOfServiceAgreed/同意 checker ${{
|
|
120
|
+
async"《服务条款》"(data) {
|
|
121
|
+
var termsOfService = await acme2.getTermsOfService();
|
|
122
|
+
if (termsOfService) window.open(termsOfService, "_blank", "popup,noopener,noreferer")
|
|
123
|
+
},
|
|
124
|
+
}}
|
|
125
|
+
`,
|
|
126
|
+
get message() {
|
|
127
|
+
return formdata.kid ? "已创建账户" : '';
|
|
128
|
+
},
|
|
129
|
+
actions: {
|
|
130
|
+
async 创建账户(actived) {
|
|
131
|
+
var params = submit(actived.fields, formdata);
|
|
132
|
+
await saveUnique(params);
|
|
133
|
+
formdata.kid = await acme2.newAccount(params);
|
|
134
|
+
await saveUnique();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"name": "创建订单",
|
|
140
|
+
get disabled() {
|
|
141
|
+
return !!formdata.kid;
|
|
142
|
+
},
|
|
143
|
+
fields: refilm`
|
|
144
|
+
$账户/kid input
|
|
145
|
+
*当前服务器的域名/domain/每行一个 text
|
|
146
|
+
`,
|
|
147
|
+
actions: {
|
|
148
|
+
async 创建订单(actived) {
|
|
149
|
+
var params = submit(actived.fields, formdata);
|
|
150
|
+
var order = await acme2.newOrder(params);
|
|
151
|
+
formdata.orders = acme2.orders;
|
|
152
|
+
await saveUnique();
|
|
153
|
+
activeMenu(menus[2], 2);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "订单信息",
|
|
159
|
+
src: '/cert/orders',
|
|
160
|
+
get params() {
|
|
161
|
+
return formdata.orders;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
var actived = null;
|
|
167
|
+
var activeMenu = function (m, i) {
|
|
168
|
+
if (actived === m) return;
|
|
169
|
+
if (actived) actived.actived = false;
|
|
170
|
+
m.actived = true;
|
|
171
|
+
actived = m;
|
|
172
|
+
activeIndex = i;
|
|
173
|
+
};
|
|
174
|
+
activeMenu(menus[0], 0);
|
|
175
|
+
var normalList = plist.bind(null, '接口管理', "cert", refilm`
|
|
176
|
+
* 域名 / hostname input / 190
|
|
177
|
+
更新连接 / url text / 290
|
|
178
|
+
密码 / password input / 290
|
|
179
|
+
`, '/cert/edit');
|
|
180
|
+
|
|
181
|
+
</script>
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
&>list,
|
|
3
|
+
&>div {
|
|
4
|
+
display: inline-block;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
& {
|
|
8
|
+
--border: 1px solid #0006;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&>xmenu[horizonal] {
|
|
12
|
+
width: 100%;
|
|
13
|
+
margin-bottom: -2px;
|
|
14
|
+
z-index: 1;
|
|
15
|
+
border-bottom: none;
|
|
16
|
+
box-shadow: none;
|
|
17
|
+
|
|
18
|
+
&:after {
|
|
19
|
+
content: "";
|
|
20
|
+
display: block;
|
|
21
|
+
position: absolute;
|
|
22
|
+
left: 0;
|
|
23
|
+
bottom: 0;
|
|
24
|
+
right: 0;
|
|
25
|
+
height: 0;
|
|
26
|
+
border-bottom: --border;
|
|
27
|
+
z-index: -1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.actived {
|
|
31
|
+
background: #fff;
|
|
32
|
+
color: #333;
|
|
33
|
+
border: --border;
|
|
34
|
+
border-bottom: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
+form {
|
|
38
|
+
border: --border;
|
|
39
|
+
background: #fff;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
[actived] {
|
|
44
|
+
background: #fff;
|
|
45
|
+
/* border-bottom: 2px solid; */
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
[status]>s {
|
|
49
|
+
width: 0;
|
|
50
|
+
height: 0;
|
|
51
|
+
border-radius: 50%;
|
|
52
|
+
display: inline-block;
|
|
53
|
+
border: .3em solid;
|
|
54
|
+
margin-right: 6px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@status(@s, @c) {
|
|
58
|
+
[status=@s] {
|
|
59
|
+
color: @c;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@status(pending, #777);
|
|
64
|
+
@status(processing, #f82);
|
|
65
|
+
@status(ready, #284);
|
|
66
|
+
@status(valid, #26c);
|
|
67
|
+
@status(invalid, #c24);
|
|
68
|
+
</style>
|
|
69
|
+
<xmenu -src="o of orders" @active="openOrder(o)"></xmenu>
|
|
70
|
+
<form -if="order?.oid" onsubmit="event.preventDefault()">
|
|
71
|
+
<div body>
|
|
72
|
+
<field -repeat="f in fields" _src="[f,order]"></field>
|
|
73
|
+
</div>
|
|
74
|
+
<div foot>
|
|
75
|
+
<button -if="order.authorizations?.length" @click="auditOrder(order)">提审</button>
|
|
76
|
+
<button -if="order.finalize">定案</button>
|
|
77
|
+
</div>
|
|
78
|
+
</form>
|
|
79
|
+
<script>
|
|
80
|
+
var fields = refilm`
|
|
81
|
+
$状态/status radio [待定/pending,完毕/ready,审核中/processing,生效/valid,无效/invalid]
|
|
82
|
+
$证书/certificate anchor
|
|
83
|
+
$域名/identifiers ${function (elem) {
|
|
84
|
+
var { field, data } = elem;
|
|
85
|
+
var value = data[field.key];
|
|
86
|
+
if (value instanceof Array) elem.innerHTML = value.map(v => `${v.value} (${v.type})`).join("<br/>")
|
|
87
|
+
else elem.innerHTML = '';
|
|
88
|
+
}}
|
|
89
|
+
$失效时间/expires ${function (elem) {
|
|
90
|
+
var { field, data } = elem;
|
|
91
|
+
elem.innerHTML = filterTime(data[field.key]);
|
|
92
|
+
}}
|
|
93
|
+
`;
|
|
94
|
+
var order = {
|
|
95
|
+
authorizations: [],
|
|
96
|
+
expires: NaN,
|
|
97
|
+
finalize: '',
|
|
98
|
+
identifiers: [],
|
|
99
|
+
status: ''
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
function main(params) {
|
|
103
|
+
var orders = params || [];
|
|
104
|
+
orders = orders.map(acme2.parseOrder);
|
|
105
|
+
orders[0].actived = true;
|
|
106
|
+
var page = document.createElement('orders');
|
|
107
|
+
page.innerHTML = template;
|
|
108
|
+
var scope = {
|
|
109
|
+
fields,
|
|
110
|
+
form: view,
|
|
111
|
+
xmenu: menu,
|
|
112
|
+
orders,
|
|
113
|
+
order: null,
|
|
114
|
+
async openOrder(o) {
|
|
115
|
+
this.order = o;
|
|
116
|
+
if (!o.oid) return;
|
|
117
|
+
var order = await acme2.getOrder(orders[0]);
|
|
118
|
+
extend(o, order);
|
|
119
|
+
if (o !== this.order) return;
|
|
120
|
+
this.order = shallowClone(o);
|
|
121
|
+
},
|
|
122
|
+
async auditOrder(o) {
|
|
123
|
+
a: for (var a of o.authorizations) {
|
|
124
|
+
var o = await acme2.audit(a);
|
|
125
|
+
if (o.challenges) {
|
|
126
|
+
for (var c of o.challenges) {
|
|
127
|
+
if (c.type === 'http-01') {
|
|
128
|
+
await data.from("setauth", { token: c.token, thumb: await acme2.thumbprint() });
|
|
129
|
+
await data.fromURL(c.url);
|
|
130
|
+
continue a;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
alert("无法找到可用的提审方案" + o.identifier?.value, 'warn');
|
|
135
|
+
}
|
|
136
|
+
await this.openOrder(this.order);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
renderWithDefaults(page, scope);
|
|
140
|
+
if (orders.length) scope.openOrder(orders[0]).then(render.digest);
|
|
141
|
+
|
|
142
|
+
return page;
|
|
143
|
+
}
|
|
144
|
+
</script>
|
package/apps/pivot/menu.yml
CHANGED
package/coms/basic/assert.js
CHANGED
|
@@ -1,18 +1,42 @@
|
|
|
1
1
|
var mark = require("./mark");
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
var format = console.format, clog = console.log;
|
|
3
|
+
if (!format) format = a => a, clog = function () {
|
|
4
|
+
var args = [];
|
|
5
|
+
var colors = {
|
|
6
|
+
green: 'color:green;',
|
|
7
|
+
gray: "color:gray;",
|
|
8
|
+
red2: "color:red;",
|
|
9
|
+
bgblue: 'background-color:blue;',
|
|
10
|
+
bgred: 'background-color:red;',
|
|
11
|
+
cyan: 'color:#29c;',
|
|
12
|
+
reset: 'color:;background-color:;',
|
|
13
|
+
}
|
|
14
|
+
for (var a of arguments) {
|
|
15
|
+
if (typeof a === "string") {
|
|
16
|
+
var tags = [];
|
|
17
|
+
a = renderTags(a, function (tag, e) {
|
|
18
|
+
var c = tag ? colors[tag] : colors.reset;
|
|
19
|
+
if (c) {
|
|
20
|
+
if (e !== false) tags.push(c);
|
|
21
|
+
return '%c'
|
|
22
|
+
}
|
|
23
|
+
return '';
|
|
24
|
+
});
|
|
25
|
+
args.push(a, ...tags);
|
|
26
|
+
}
|
|
27
|
+
else args.push(a);
|
|
28
|
+
}
|
|
29
|
+
console.log(...args);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
var gray = format('<gray>;</gray>').split(';');
|
|
34
|
+
var green = format('<green>;</green>').split(';');
|
|
35
|
+
var crack = format('<red2>;</red2>').split(';');
|
|
12
36
|
var dump = function (a, msg) {
|
|
13
|
-
if (a instanceof Object) console.error(i18n`属性错误`),
|
|
14
|
-
else if (msg)
|
|
15
|
-
else
|
|
37
|
+
if (a instanceof Object) console.error(i18n`属性错误`), clog(msg ? msg + " " : " {\r\n", Object.keys(a).map(k => ` ${k}${gray.join(':')}\r\n ${a[k]}`).join('\r\n') + "\r\n }");
|
|
38
|
+
else if (msg) clog(msg + ":", a);
|
|
39
|
+
else clog(a);
|
|
16
40
|
};
|
|
17
41
|
var colorString = function (s, color1, e, color2) {
|
|
18
42
|
s = String(s);
|
|
@@ -35,9 +59,9 @@ var assert = function (result, expect, log = dump) {
|
|
|
35
59
|
errors = `结果 (${args}) 应为 ${JSON.stringify(k)}`;
|
|
36
60
|
}
|
|
37
61
|
if (k === undefined) return function () {
|
|
38
|
-
var color1 =
|
|
39
|
-
var color2 =
|
|
40
|
-
var color3 =
|
|
62
|
+
var color1 = format("<bgred>; </bgred>").split(";");
|
|
63
|
+
var color2 = format("<bgblue>; </bgblue>").split(";");
|
|
64
|
+
var color3 = format("<cyan>;</cyan>").split(";");
|
|
41
65
|
mark.setTag1(color1[1], color1[0]);
|
|
42
66
|
mark.setTag2(color2[1], color2[0]);
|
|
43
67
|
var [r, e] = mark.pair(result, expect);
|
package/coms/basic/cross_.js
CHANGED
|
@@ -20,7 +20,7 @@ var setHost = function (host) {
|
|
|
20
20
|
base = host;
|
|
21
21
|
encrypt = null;
|
|
22
22
|
};
|
|
23
|
-
var
|
|
23
|
+
var RealHeadersKeys = { "content-type": "Content-Type" };
|
|
24
24
|
var cors_hosts = [];
|
|
25
25
|
function getDomainPath(url) {
|
|
26
26
|
return url.replace(domainReg, "$2/$3");
|
|
@@ -330,7 +330,18 @@ function cross_(jsonp, digest = noop, method, url, headers) {
|
|
|
330
330
|
}
|
|
331
331
|
else if (cachedata.length && isEmpty(datas)) {
|
|
332
332
|
var jsondata = mergedata(cachedata, parseKV);
|
|
333
|
-
if (
|
|
333
|
+
if (realHeaders["Content-Type"]) {
|
|
334
|
+
if (/json$/i.test(realHeaders["Content-Type"])) {
|
|
335
|
+
datas = JSON.stringify(jsondata);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
if (hasFile(jsondata)) {
|
|
339
|
+
datas = kv2form(jsondata);
|
|
340
|
+
}
|
|
341
|
+
else datas = serialize(jsondata, '&', "=");
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
else if (isform) {
|
|
334
345
|
var hasfile = hasFile(jsondata);
|
|
335
346
|
if (hasfile) {
|
|
336
347
|
datas = kv2form(jsondata);
|
|
@@ -383,7 +394,13 @@ function cross_(jsonp, digest = noop, method, url, headers) {
|
|
|
383
394
|
}
|
|
384
395
|
}
|
|
385
396
|
else {
|
|
386
|
-
|
|
397
|
+
var k1 = RealHeadersKeys[k.toLowerCase()];
|
|
398
|
+
if (k1) {
|
|
399
|
+
realHeaders[k1] = headers[k];
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
_headers[k] = headers[k];
|
|
403
|
+
}
|
|
387
404
|
}
|
|
388
405
|
}
|
|
389
406
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
var tagReg = /<(\/?)([a-z][\w]*)\>/ig;
|
|
2
|
+
// 只应用一种效果,多种效果不能同时存在
|
|
3
|
+
function renderTags(str, getTag) {
|
|
4
|
+
var tagpath = [];
|
|
5
|
+
return String(str).replace(tagReg, function (_, e, c) {
|
|
6
|
+
if (!c || c.length < 3) return _;
|
|
7
|
+
var t = getTag(c, false);
|
|
8
|
+
if (!t) return _;
|
|
9
|
+
if (e) {
|
|
10
|
+
tagpath.pop();
|
|
11
|
+
c = tagpath[tagpath.length - 1];
|
|
12
|
+
}
|
|
13
|
+
else tagpath.push(c);
|
|
14
|
+
var res = [];
|
|
15
|
+
if (e) res.push(getTag());
|
|
16
|
+
if (c) res.push(getTag(c));
|
|
17
|
+
if (res.length) return res.join('');
|
|
18
|
+
return _;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
renderTags.reg = tagReg;
|
|
23
|
+
module.exports = renderTags;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
var shallowClone = function (origin, deep) {
|
|
2
|
+
if (--deep < 0) return origin;
|
|
3
|
+
if (!isObject(origin)) return origin;
|
|
4
|
+
var temp = origin instanceof Array ? [] : {};
|
|
5
|
+
if (deep > 0) for (var k in origin) temp[k] = shallowClone(origin[k], deep);
|
|
6
|
+
else for (var k in origin) temp[k] = origin[k];
|
|
7
|
+
return temp;
|
|
8
|
+
}
|
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
var singleEqual = isSame;
|
|
2
|
-
function shallowEqual(o1, o2) {
|
|
2
|
+
function shallowEqual(o1, o2, deep) {
|
|
3
3
|
// 浅层比对,对内层对象不进行递归比对
|
|
4
|
-
if (
|
|
4
|
+
if (--deep < 0) return singleEqual(o1, o2);
|
|
5
|
+
if (singleEqual(o1, o2)) return true;
|
|
5
6
|
if (isObject(o1) && isObject(o2)) {
|
|
6
7
|
var keys1 = Object.keys(o1), keys2 = Object.keys(o2);
|
|
7
8
|
if (keys1.length !== keys2.length) return false;
|
|
8
9
|
keys1.sort(), keys2.sort();
|
|
10
|
+
var rest = [];
|
|
9
11
|
for (var cx = 0, dx = keys1.length; cx < dx; cx++) {
|
|
10
12
|
var key1 = keys1[cx];
|
|
11
13
|
var key2 = keys2[cx];
|
|
12
14
|
if (key1 !== key2) return false;
|
|
13
|
-
|
|
15
|
+
var v1 = o1[key1], v2 = o2[key2];
|
|
16
|
+
if (!singleEqual(v1, v2)) {
|
|
17
|
+
if (deep) rest.push(v1, v2);
|
|
18
|
+
else return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (deep > 0) for (var cx = 0, dx = rest.length; cx < dx;) {
|
|
22
|
+
if (!shallowEqual(rest[cx++], rest[cx++], deep)) return false;
|
|
14
23
|
}
|
|
15
24
|
return true;
|
|
16
25
|
}
|
|
17
|
-
return
|
|
26
|
+
return false;
|
|
18
27
|
}
|
package/coms/basic/valid.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
var validators = {
|
|
2
|
+
email(text) {
|
|
3
|
+
var i = text.indexOf('@');
|
|
4
|
+
if (i < 0) return i18n`电子邮箱地址应包含符号“@”`;
|
|
5
|
+
if (i === 0) return i18n`@符号前应有内容`;
|
|
6
|
+
if (i === text.length - 1) return i18n`@符号后应有内容`;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
1
9
|
function valid(field, data) {
|
|
2
10
|
var error;
|
|
3
11
|
if (isEmpty(data[field.key])) {
|
|
@@ -6,8 +14,13 @@ function valid(field, data) {
|
|
|
6
14
|
}
|
|
7
15
|
return;
|
|
8
16
|
}
|
|
9
|
-
var tmp;
|
|
10
|
-
if (tmp
|
|
17
|
+
var tmp = validators[field.type];
|
|
18
|
+
if (tmp) {
|
|
19
|
+
var value = data[field.key];
|
|
20
|
+
var error = tmp(String(value ?? ''));
|
|
21
|
+
if (error) return error;
|
|
22
|
+
}
|
|
23
|
+
else if (tmp = /\:(\d+)(?:\.(\d+))?$/.exec(field.type)) {
|
|
11
24
|
var [, a, b] = tmp;
|
|
12
25
|
var value = data[field.key];
|
|
13
26
|
a = +a;
|
|
@@ -401,7 +401,6 @@ var getFromScopeList = function (name, varsList, value = name) {
|
|
|
401
401
|
};
|
|
402
402
|
var removeSelectorSpace = a => a.trim().replace(/\s*([\+~\>])\s*/g, "$1");
|
|
403
403
|
var fixBase = function (b, a) {
|
|
404
|
-
var s = splitParams(a);
|
|
405
404
|
return splitParams(a).map(a => {
|
|
406
405
|
if (presets.test(a)) a = `@{${a}}`;
|
|
407
406
|
var replaced = false;
|
|
@@ -426,9 +425,11 @@ function evalscoped(scoped, base = '') {
|
|
|
426
425
|
base = removeSelectorSpace(base);
|
|
427
426
|
var smaps = scoped.maps;
|
|
428
427
|
var root = smaps[":root"], scope = smaps[":scope"];
|
|
428
|
+
var and = smaps["&"];
|
|
429
429
|
var vars = extend(Object.create(null), scoped.vars);
|
|
430
430
|
if (root) root.forEach(r => extend(vars, r.vars));
|
|
431
431
|
if (scope) scope.forEach(s => extend(vars, s.vars));
|
|
432
|
+
if (and) and.forEach(a => extend(vars, a.vars));
|
|
432
433
|
var vlist = [vars];
|
|
433
434
|
var mlist = [macros];
|
|
434
435
|
var clist = [smaps];
|
package/coms/docs/codetext.xht
CHANGED
|
@@ -109,8 +109,8 @@
|
|
|
109
109
|
case QUOTED:
|
|
110
110
|
if (o.length || !o.text) {
|
|
111
111
|
o.forEach(setcolor);
|
|
112
|
-
o.entry = "<text>" + o.entry;
|
|
113
|
-
o.leave = o.leave + "</text>";
|
|
112
|
+
o.entry = "<text>" + o.entry + "</text>";
|
|
113
|
+
o.leave = "<text>" + o.leave + "</text>";
|
|
114
114
|
break;
|
|
115
115
|
}
|
|
116
116
|
case PIECE:
|
|
@@ -299,7 +299,7 @@
|
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
if (minSpace > 0) codes = codes.map(c => /^\s+/.test(c) ? c.slice(minSpace) : c);
|
|
302
|
-
return `<code type=${type}>${codes.join("<br/>").replace(/\t/g, Array(5).join(' ')).replace(/\s/g, ' ')}</code
|
|
302
|
+
return `<code type=${type}>${codes.join("<br/>").replace(/\t/g, Array(5).join(' ')).replace(/\s/g, ' ')}</code>`;
|
|
303
303
|
}
|
|
304
304
|
codetext.encode = encode;
|
|
305
305
|
</script>
|