chanjs 2.6.13 → 2.6.15

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.
@@ -4,7 +4,7 @@ import { createRequire } from 'module';
4
4
  const require = createRequire(import.meta.url);
5
5
  const { marked } = require('marked');
6
6
 
7
- //template.defaults.native = false; // 禁用原生模板引擎 防止模板直接调用nodejs语法
7
+ template.defaults.native = false; // 禁用原生模板引擎 防止模板直接调用nodejs语法
8
8
  //template.defaults.debug = false; // 禁用调试模式
9
9
 
10
10
 
@@ -41,13 +41,29 @@ template.defaults.imports.truncate = (str, length = 10) => {
41
41
  };
42
42
 
43
43
  /**
44
- * 安全JSON序列化过滤器
44
+ * 安全的 JSON 序列化过滤器
45
+ * 用于在模板中调试和显示对象内容
45
46
  * @param {Object} obj - 要序列化的对象
47
+ * @param {Array} keys - 可选,只返回指定的字段
46
48
  * @returns {string} JSON字符串
47
49
  */
48
- template.defaults.imports.safeStringify = (obj) => {
50
+ template.defaults.imports.safeStringify = (obj, keys) => {
51
+ if (!obj) return 'null';
52
+
53
+ // 如果指定了 keys,只返回这些字段
54
+ if (keys && Array.isArray(keys) && keys.length > 0) {
55
+ const filteredObj = {};
56
+ keys.forEach(key => {
57
+ if (obj.hasOwnProperty(key)) {
58
+ filteredObj[key] = obj[key];
59
+ }
60
+ });
61
+ return JSON.stringify(filteredObj, null, 2);
62
+ }
63
+
64
+ // 否则返回完整对象
49
65
  return JSON.stringify(obj, null, 2);
50
- };
66
+ };
51
67
 
52
68
  /**
53
69
  * Markdown 渲染过滤器
@@ -55,15 +71,29 @@ template.defaults.imports.safeStringify = (obj) => {
55
71
  * @param {string} content - 文章内容
56
72
  * @returns {string} 渲染后的 HTML
57
73
  */
58
- template.defaults.imports.renderMarkdown = (content) => {
74
+ template.defaults.imports.renderContent = (content, editorType = 'rich', allowScript = 0) => {
59
75
  if (!content || typeof content !== 'string') {
60
76
  return content || '';
61
77
  }
62
78
 
63
- try {
64
- return marked.parse(content);
65
- } catch (err) {
66
- console.error('[renderMarkdown] Markdown 渲染失败:', err.message);
67
- return content;
79
+ let html = content;
80
+
81
+ // Markdown 需要转换
82
+ if (editorType === 'md') {
83
+ try {
84
+ html = marked.parse(content);
85
+ } catch (err) {
86
+ console.error('[renderContent] Markdown 渲染失败:', err.message);
87
+ html = content;
88
+ }
89
+ }
90
+
91
+ // 如果 allowScript !== 1,转义 script 标签
92
+ if (Number(allowScript) !== 1) {
93
+ html = html
94
+ .replace(/<script\b[^>]*>/gi, '&amp;lt;script&amp;gt;')
95
+ .replace(/<\/script>/gi, '&amp;lt;/script&amp;gt;');
68
96
  }
97
+
98
+ return html;
69
99
  };
package/helper/html.js CHANGED
@@ -1,30 +1,40 @@
1
1
  /**
2
- * 解码 HTML 实体字符
3
- * @param {string} str - 包含 HTML 实体的字符串
4
- * @returns {string} 解码后的字符串,如果输入为空则返回空字符串
5
- * @description
6
- * 将 HTML 实体字符转换为对应的普通字符
7
- * 支持的实体字符:
8
- * - &amp; -> &
9
- * - &lt; -> <
10
- * - &gt; -> >
11
- * - &quot; -> "
12
- * - &apos; -> '
13
- * - &nbsp; -> 空格
14
- * @example
15
- * const html = '&lt;div&gt;Hello &amp; World&lt;/div&gt;';
16
- * const decoded = htmlDecode(html);
17
- * console.log(decoded); // '<div>Hello & World</div>'
2
+ * 标准 HTML 编码(art-template {{}} 使用)
3
+ */
4
+ export function htmlEncode(str) {
5
+ if (typeof str !== 'string') return '';
6
+ return str
7
+ .replace(/&/g, '&amp;')
8
+ .replace(/</g, '&lt;')
9
+ .replace(/>/g, '&gt;')
10
+ .replace(/"/g, '&quot;')
11
+ .replace(/'/g, '&apos;');
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
+ // 二次转义 → 经过 {{@}} 解码后变成 &lt;script&gt;
22
+ .replace(/<script\b[^>]*>/gi, '&amp;lt;script&amp;gt;')
23
+ .replace(/<\/script>/gi, '&amp;lt;/script&amp;gt;');
24
+ };
25
+
26
+ /**
27
+ * HTML 解码
18
28
  */
19
29
  export function htmlDecode(str) {
20
- if (!str) return "";
21
- const htmlEntities = {
22
- "&amp;": "&",
23
- "&lt;": "<",
24
- "&gt;": ">",
25
- "&quot;": '"',
26
- "&apos;": "'",
27
- "&nbsp;": " ",
30
+ if (typeof str !== 'string') return '';
31
+ const entities = {
32
+ '&amp;': '&',
33
+ '&lt;': '<',
34
+ '&gt;': '>',
35
+ '&quot;': '"',
36
+ '&apos;': "'",
37
+ '&nbsp;': ' ',
28
38
  };
29
- return str.replace(/&[a-z]+;/gi, (match) => htmlEntities[match] || match);
30
- }
39
+ return str.replace(/&(amp|lt|gt|quot|apos|nbsp);/g, m => entities[m]);
40
+ }
package/helper/index.js CHANGED
@@ -19,7 +19,7 @@ export {
19
19
  } from "./file.js";
20
20
 
21
21
  // HTML处理
22
- export { htmlDecode } from "./html.js";
22
+ export { htmlDecode, htmlEncode,escapeScript } from "./html.js";
23
23
 
24
24
  // IP相关
25
25
  export { getIp } from "./ip.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "chanjs",
4
- "version": "2.6.13",
4
+ "version": "2.6.15",
5
5
  "description": "chanjs基于express5 纯js研发的轻量级mvc框架。",
6
6
  "main": "index.js",
7
7
  "module": "index.js",
@@ -24,14 +24,14 @@
24
24
  "cookie-parser": "^1.4.7",
25
25
  "cors": "^2.8.6",
26
26
  "dotenv": "^17.4.2",
27
- "dayjs": "^1.11.20",
27
+ "dayjs": "^1.11.21",
28
28
  "express": "^5.2.1",
29
29
  "express-art-template": "^1.0.1",
30
30
  "ip2region": "^2.3.0",
31
31
  "knex": "^3.2.10",
32
32
  "morgan": "^1.10.1",
33
- "mysql2": "^3.22.3",
33
+ "mysql2": "^3.22.4",
34
34
  "sqlite3": "^6.0.1",
35
- "marked": "^18.0.3"
35
+ "marked": "^18.0.4"
36
36
  }
37
37
  }