chanjs 2.6.14 → 2.6.16
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/extend/art-template.js +51 -7
- package/helper/html.js +36 -26
- package/helper/index.js +1 -1
- package/middleware/waf.js +1 -0
- package/package.json +6 -3
package/extend/art-template.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import template from "art-template";
|
|
2
2
|
import dayjs from "dayjs";
|
|
3
|
+
import relativeTime from "dayjs/plugin/relativeTime.js";
|
|
4
|
+
import "dayjs/locale/zh-cn.js";
|
|
3
5
|
import { createRequire } from 'module';
|
|
4
6
|
const require = createRequire(import.meta.url);
|
|
5
7
|
const { marked } = require('marked');
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
dayjs.extend(relativeTime);
|
|
10
|
+
dayjs.locale('zh-cn');
|
|
11
|
+
|
|
12
|
+
template.defaults.native = false; // 禁用原生模板引擎 防止模板直接调用nodejs语法
|
|
8
13
|
//template.defaults.debug = false; // 禁用调试模式
|
|
9
14
|
|
|
10
15
|
|
|
@@ -30,6 +35,18 @@ template.defaults.imports.dateFormat = function (date, format) {
|
|
|
30
35
|
return date.format(format);
|
|
31
36
|
};
|
|
32
37
|
|
|
38
|
+
/**
|
|
39
|
+
* 相对时间过滤器(如"刚刚"、"5分钟前"、"3小时前")
|
|
40
|
+
* @param {Date|string|number} date - 日期对象、日期字符串或时间戳
|
|
41
|
+
* @returns {string} 相对时间字符串
|
|
42
|
+
*/
|
|
43
|
+
template.defaults.imports.timeAgo = function (date) {
|
|
44
|
+
if (!date) return "";
|
|
45
|
+
const d = dayjs(date);
|
|
46
|
+
if (!d.isValid()) return "";
|
|
47
|
+
return d.fromNow();
|
|
48
|
+
};
|
|
49
|
+
|
|
33
50
|
/**
|
|
34
51
|
* 字符串截断过滤器
|
|
35
52
|
* @param {string} str - 原始字符串
|
|
@@ -65,21 +82,48 @@ template.defaults.imports.safeStringify = (obj, keys) => {
|
|
|
65
82
|
return JSON.stringify(obj, null, 2);
|
|
66
83
|
};
|
|
67
84
|
|
|
85
|
+
/**
|
|
86
|
+
* 获取对象所有key的过滤器,方便调试查看数据结构
|
|
87
|
+
* 用法:{{$data | objKeys}} 或 {{$data | objKeys ','}}
|
|
88
|
+
* @param {Object} obj - 要获取key的对象
|
|
89
|
+
* @param {string} separator - 分隔符,默认为换行
|
|
90
|
+
* @returns {string} 所有key的字符串
|
|
91
|
+
*/
|
|
92
|
+
template.defaults.imports.objKeys = (obj, separator) => {
|
|
93
|
+
if (!obj || typeof obj !== 'object') return '';
|
|
94
|
+
const sep = separator !== undefined ? separator : '\n';
|
|
95
|
+
return Object.keys(obj).join(sep);
|
|
96
|
+
};
|
|
97
|
+
|
|
68
98
|
/**
|
|
69
99
|
* Markdown 渲染过滤器
|
|
70
100
|
* 自动检测内容是否为 Markdown 格式,如果是则渲染为 HTML
|
|
71
101
|
* @param {string} content - 文章内容
|
|
72
102
|
* @returns {string} 渲染后的 HTML
|
|
73
103
|
*/
|
|
74
|
-
template.defaults.imports.
|
|
104
|
+
template.defaults.imports.renderContent = (content, editorType = 'rich', allowScript = 0) => {
|
|
75
105
|
if (!content || typeof content !== 'string') {
|
|
76
106
|
return content || '';
|
|
77
107
|
}
|
|
78
108
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
109
|
+
let html = content;
|
|
110
|
+
|
|
111
|
+
// Markdown 需要转换
|
|
112
|
+
if (editorType === 'md') {
|
|
113
|
+
try {
|
|
114
|
+
html = marked.parse(content);
|
|
115
|
+
} catch (err) {
|
|
116
|
+
console.error('[renderContent] Markdown 渲染失败:', err.message);
|
|
117
|
+
html = content;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 如果 allowScript !== 1,转义 script 标签
|
|
122
|
+
if (Number(allowScript) !== 1) {
|
|
123
|
+
html = html
|
|
124
|
+
.replace(/<script\b[^>]*>/gi, '&lt;script&gt;')
|
|
125
|
+
.replace(/<\/script>/gi, '&lt;/script&gt;');
|
|
84
126
|
}
|
|
127
|
+
|
|
128
|
+
return html;
|
|
85
129
|
};
|
package/helper/html.js
CHANGED
|
@@ -1,30 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
|
|
2
|
+
* 标准 HTML 编码(art-template {{}} 使用)
|
|
3
|
+
*/
|
|
4
|
+
export function htmlEncode(str) {
|
|
5
|
+
if (typeof str !== 'string') return '';
|
|
6
|
+
return str
|
|
7
|
+
.replace(/&/g, '&')
|
|
8
|
+
.replace(/</g, '<')
|
|
9
|
+
.replace(/>/g, '>')
|
|
10
|
+
.replace(/"/g, '"')
|
|
11
|
+
.replace(/'/g, ''');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 【适配 art-template {{@}}】二次转义 script 标签
|
|
16
|
+
* 必须这样写才能防 XSS!
|
|
17
|
+
*/
|
|
18
|
+
export const escapeScript = (str) => {
|
|
19
|
+
if (typeof str !== 'string') return '';
|
|
20
|
+
return str
|
|
21
|
+
// 二次转义 → 经过 {{@}} 解码后变成 <script>
|
|
22
|
+
.replace(/<script\b[^>]*>/gi, '&lt;script&gt;')
|
|
23
|
+
.replace(/<\/script>/gi, '&lt;/script&gt;');
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* HTML 解码
|
|
18
28
|
*/
|
|
19
29
|
export function htmlDecode(str) {
|
|
20
|
-
if (
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
if (typeof str !== 'string') return '';
|
|
31
|
+
const entities = {
|
|
32
|
+
'&': '&',
|
|
33
|
+
'<': '<',
|
|
34
|
+
'>': '>',
|
|
35
|
+
'"': '"',
|
|
36
|
+
''': "'",
|
|
37
|
+
' ': ' ',
|
|
28
38
|
};
|
|
29
|
-
return str.replace(/&
|
|
30
|
-
}
|
|
39
|
+
return str.replace(/&(amp|lt|gt|quot|apos|nbsp);/g, m => entities[m]);
|
|
40
|
+
}
|
package/helper/index.js
CHANGED
package/middleware/waf.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "chanjs",
|
|
4
|
-
"version": "2.6.
|
|
4
|
+
"version": "2.6.16",
|
|
5
5
|
"description": "chanjs基于express5 纯js研发的轻量级mvc框架。",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"module": "index.js",
|
|
@@ -23,15 +23,18 @@
|
|
|
23
23
|
"body-parser": "^2.2.2",
|
|
24
24
|
"cookie-parser": "^1.4.7",
|
|
25
25
|
"cors": "^2.8.6",
|
|
26
|
-
"dotenv": "^17.4.2",
|
|
27
26
|
"dayjs": "^1.11.20",
|
|
27
|
+
"dotenv": "^17.4.2",
|
|
28
28
|
"express": "^5.2.1",
|
|
29
29
|
"express-art-template": "^1.0.1",
|
|
30
30
|
"ip2region": "^2.3.0",
|
|
31
|
+
"jsonwebtoken": "^9.0.3",
|
|
31
32
|
"knex": "^3.2.10",
|
|
33
|
+
"marked": "^18.0.3",
|
|
32
34
|
"morgan": "^1.10.1",
|
|
33
35
|
"mysql2": "^3.22.3",
|
|
36
|
+
"serve-favicon": "^2.5.1",
|
|
34
37
|
"sqlite3": "^6.0.1",
|
|
35
|
-
"
|
|
38
|
+
"xss": "^1.0.15"
|
|
36
39
|
}
|
|
37
40
|
}
|