@codady/utils 0.0.1

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/script-note.js ADDED
@@ -0,0 +1,34 @@
1
+
2
+ /**
3
+ * Last modified: 2025/11/15 11:09:56
4
+ */
5
+ import { readFileSync } from 'fs';
6
+ import { fileURLToPath } from 'url';
7
+ import { dirname, resolve } from 'path';
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+
12
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, './package.json'), 'utf8'));
13
+
14
+ const now = new Date();
15
+ const times = now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate() + ' ' + now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds();
16
+
17
+ const note = `
18
+ /*!
19
+ * @since Last modified: ${times}
20
+ * @name Utils for web front-end.
21
+ * @version ${pkg.version}
22
+ * @author AXUI development team <3217728223@qq.com>
23
+ * @description This is a set of general-purpose JavaScript utility functions developed by the AXUI team. All functions are pure and do not involve CSS or other third-party libraries. They are suitable for any web front-end environment.
24
+ * @see {@link https://www.axui.cn|Official website}
25
+ * @see {@link https://github.com/codady/utils/issues|github issues}
26
+ * @see {@link https://gitee.com/codady/utils/issues|Gitee issues}
27
+ * @see {@link https://www.npmjs.com/package/@codady/utils|NPM}
28
+ * @issue QQ Group No.1:952502085
29
+ * @copyright This software supports the MIT License, allowing free learning and commercial use, but please retain the terms 'ax,' 'axui,' 'AX,' and 'AXUI' within the software.
30
+ * @license MIT license
31
+ */
32
+ `;
33
+
34
+ export default note;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @since Last modified: 2025/12/16 09:02:07
3
+ * Deep clone an array or object.
4
+ * Supports Symbol keys. These types are returned directly:
5
+ * Number, String, Boolean, Symbol, HTML*Element, Function, Date, RegExp.
6
+ *
7
+ * @template T
8
+ * @param {T} data - Array or object to clone
9
+ * @returns {T} - New object with different memory address
10
+ *
11
+ * @example
12
+ * const obj = { a: '', b: 0, c: [] };
13
+ * const cloned = deepClone(obj);
14
+ *
15
+ * @example
16
+ * const arr = [{}, {}, {}];
17
+ * const cloned = deepClone(arr);
18
+ */
19
+ 'use strict';
20
+ import getDataType from './getDataType';
21
+ const deepClone = (data) => {
22
+ const dataType = getDataType(data);
23
+ if (dataType === 'Object') {
24
+ const newObj = {};
25
+ const symbols = Object.getOwnPropertySymbols(data);
26
+ // Clone regular properties
27
+ for (const key in data) {
28
+ newObj[key] = deepClone(data[key]);
29
+ }
30
+ // Clone Symbol properties
31
+ if (symbols.length > 0) {
32
+ for (const symbol of symbols) {
33
+ newObj[symbol] = deepClone(data[symbol]);
34
+ }
35
+ }
36
+ return newObj;
37
+ }
38
+ else if (dataType === 'Array') {
39
+ return data.map(item => deepClone(item));
40
+ }
41
+ else if (dataType === 'Date') {
42
+ return new Date(data.getTime());
43
+ }
44
+ else if (dataType === 'RegExp') {
45
+ const regex = data;
46
+ return new RegExp(regex.source, regex.flags);
47
+ }
48
+ else {
49
+ // Number, String, Boolean, Symbol,Text,Comment,Set,Map, HTML*Element, Function,Error,Promise,ArrayBuffer,Blob,File, return directly
50
+ return data;
51
+ }
52
+ };
53
+ export default deepClone;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @since Last modified: 2025/12/16 09:02:07
3
+ * Deep clone an array or object.
4
+ * Supports Symbol keys. These types are returned directly:
5
+ * Number, String, Boolean, Symbol, HTML*Element, Function, Date, RegExp.
6
+ *
7
+ * @template T
8
+ * @param {T} data - Array or object to clone
9
+ * @returns {T} - New object with different memory address
10
+ *
11
+ * @example
12
+ * const obj = { a: '', b: 0, c: [] };
13
+ * const cloned = deepClone(obj);
14
+ *
15
+ * @example
16
+ * const arr = [{}, {}, {}];
17
+ * const cloned = deepClone(arr);
18
+ */
19
+ 'use strict';
20
+ import getDataType from './getDataType';
21
+
22
+ const deepClone = <T>(data: T): T => {
23
+ const dataType = getDataType(data);
24
+
25
+ if (dataType === 'Object') {
26
+ const newObj: Record<string | symbol, any> = {};
27
+ const symbols = Object.getOwnPropertySymbols(data);
28
+
29
+ // Clone regular properties
30
+ for (const key in data) {
31
+ newObj[key] = deepClone((data as any)[key]);
32
+ }
33
+
34
+ // Clone Symbol properties
35
+ if (symbols.length > 0) {
36
+ for (const symbol of symbols) {
37
+ newObj[symbol] = deepClone((data as any)[symbol]);
38
+ }
39
+ }
40
+
41
+ return newObj as T;
42
+
43
+ } else if (dataType === 'Array') {
44
+ return (data as any[]).map(item => deepClone(item)) as T;
45
+
46
+ } else if (dataType === 'Date') {
47
+ return new Date((data as Date).getTime()) as T;
48
+
49
+ } else if (dataType === 'RegExp') {
50
+ const regex = data as RegExp;
51
+ return new RegExp(regex.source, regex.flags) as T;
52
+
53
+ } else {
54
+ // Number, String, Boolean, Symbol,Text,Comment,Set,Map, HTML*Element, Function,Error,Promise,ArrayBuffer,Blob,File, return directly
55
+ return data;
56
+ }
57
+ };
58
+
59
+ export default deepClone;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @function escapeHTML
3
+ * @description Escapes HTML characters in a string to prevent XSS attacks.
4
+ * This function replaces special characters such as <, >, &, ", ', etc. with their corresponding HTML entities.
5
+ *
6
+ * @param {string} str - The input string to be escaped.
7
+ * @returns {string} - The escaped string with special HTML characters replaced by HTML entities.
8
+ *
9
+ * @example
10
+ * escapeHTML("<div>Hello & 'world'</div>");
11
+ * // returns "&lt;div&gt;Hello &amp; &#39;world&#39;&lt;/div&gt;"
12
+ */
13
+ export const escapeHTML = (str) => {
14
+ // Mapping of HTML special characters to their corresponding HTML entities
15
+ const escapes = {
16
+ '&': '&amp;',
17
+ '<': '&lt;',
18
+ '>': '&gt;',
19
+ '"': '&quot;',
20
+ "'": '&#39;',
21
+ '`': '&#96;',
22
+ '=': '&#61;',
23
+ '/': '&#47;'
24
+ };
25
+ // Replace each special character in the input string with its corresponding HTML entity
26
+ return str.replace(/[&<>"'`=\/]/g, (match) => {
27
+ return escapes[match];
28
+ });
29
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @function escapeHTML
3
+ * @description Escapes HTML characters in a string to prevent XSS attacks.
4
+ * This function replaces special characters such as <, >, &, ", ', etc. with their corresponding HTML entities.
5
+ *
6
+ * @param {string} str - The input string to be escaped.
7
+ * @returns {string} - The escaped string with special HTML characters replaced by HTML entities.
8
+ *
9
+ * @example
10
+ * escapeHTML("<div>Hello & 'world'</div>");
11
+ * // returns "&lt;div&gt;Hello &amp; &#39;world&#39;&lt;/div&gt;"
12
+ */
13
+ export const escapeHTML = (str) => {
14
+ // Mapping of HTML special characters to their corresponding HTML entities
15
+ const escapes = {
16
+ '&': '&amp;',
17
+ '<': '&lt;',
18
+ '>': '&gt;',
19
+ '"': '&quot;',
20
+ "'": '&#39;',
21
+ '`': '&#96;',
22
+ '=': '&#61;',
23
+ '/': '&#47;'
24
+ };
25
+ // Replace each special character in the input string with its corresponding HTML entity
26
+ return str.replace(/[&<>"'`=\/]/g, (match) => {
27
+ return escapes[match];
28
+ });
29
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @function escapeHTML
3
+ * @description Escapes HTML characters in a string to prevent XSS attacks.
4
+ * This function replaces special characters such as <, >, &, ", ', etc. with their corresponding HTML entities.
5
+ *
6
+ * @param {string} str - The input string to be escaped.
7
+ * @returns {string} - The escaped string with special HTML characters replaced by HTML entities.
8
+ *
9
+ * @example
10
+ * escapeHTML("<div>Hello & 'world'</div>");
11
+ * // returns "&lt;div&gt;Hello &amp; &#39;world&#39;&lt;/div&gt;"
12
+ */
13
+ export const escapeHTML = (str: string): string => {
14
+ // Mapping of HTML special characters to their corresponding HTML entities
15
+ const escapes: { [key: string]: string } = {
16
+ '&': '&amp;',
17
+ '<': '&lt;',
18
+ '>': '&gt;',
19
+ '"': '&quot;',
20
+ "'": '&#39;',
21
+ '`': '&#96;',
22
+ '=': '&#61;',
23
+ '/': '&#47;'
24
+ };
25
+
26
+ // Replace each special character in the input string with its corresponding HTML entity
27
+ return str.replace(/[&<>"'`=\/]/g, (match) => {
28
+ return escapes[match];
29
+ });
30
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @function escapeHTML
3
+ * @description Escapes HTML characters in a string to prevent XSS attacks.
4
+ * This function replaces special characters such as <, >, &, ", ', etc. with their corresponding HTML entities.
5
+ *
6
+ * @param {string} str - The input string to be escaped.
7
+ * @returns {string} - The escaped string with special HTML characters replaced by HTML entities.
8
+ *
9
+ * @example
10
+ * escapeHTML("<div>Hello & 'world'</div>");
11
+ * // returns "&lt;div&gt;Hello &amp; &#39;world&#39;&lt;/div&gt;"
12
+ */
13
+ export const escapeHTML = (str) => {
14
+ // Mapping of HTML special characters to their corresponding HTML entities
15
+ const escapes = {
16
+ '&': '&amp;',
17
+ '<': '&lt;',
18
+ '>': '&gt;',
19
+ '"': '&quot;',
20
+ "'": '&#39;',
21
+ '`': '&#96;',
22
+ '=': '&#61;',
23
+ '/': '&#47;'
24
+ };
25
+ // Replace each special character in the input string with its corresponding HTML entity
26
+ return str.replace(/[&<>"'`=\/]/g, (match) => {
27
+ return escapes[match];
28
+ });
29
+ };
@@ -0,0 +1,36 @@
1
+ import requireTypes from "./requireTypes";
2
+ /**
3
+ * @since Last modified: 2025/11/15 17:36:19
4
+ * @function executeStr
5
+ * @description Executes dynamic JavaScript code with data binding. Supports strict mode and data objects.
6
+ * The function allows the dynamic execution of code with optional binding of the provided data to the function context.
7
+ * If `splitData` is true, the data is split into keys and values for parameterized function execution.
8
+ * This function dynamically generates and executes a new function based on the provided content.
9
+ *
10
+ * @param {string} content - The JavaScript code as a string to execute. This code can contain variables that will be replaced with data values.
11
+ * @param {object|array} data - The data object or array to bind to the code. This is used to replace placeholders or reference `this` inside the code.
12
+ * @param {boolean} [splitData=false] - Whether to split the data into keys and values. If true, the `data` object is converted into individual parameters.
13
+ * @returns {any} - The result of the executed code. This could be any type depending on the content of the code being executed.
14
+ *
15
+ */
16
+ const executeStr = (content, data, splitData = false) => {
17
+ //content要求是字符串格式
18
+ requireTypes(content, 'string', (error) => {
19
+ console.error(error);
20
+ return;
21
+ });
22
+ let dataType = requireTypes(data, ['array', 'object'], (error) => {
23
+ console.error(error);
24
+ return;
25
+ }), result;
26
+ if (splitData && dataType === 'Object') {
27
+ let keys = Object.keys(data), values = Object.values(data), tmp = new Function(...keys, content).bind(data);
28
+ result = tmp(...values);
29
+ }
30
+ else {
31
+ const tmp = new Function(content).apply(data);
32
+ result = tmp();
33
+ }
34
+ return result;
35
+ };
36
+ export default executeStr;
@@ -0,0 +1,42 @@
1
+ import requireTypes from "./requireTypes";
2
+
3
+ /**
4
+ * @since Last modified: 2025/11/15 17:36:19
5
+ * @function executeStr
6
+ * @description Executes dynamic JavaScript code with data binding. Supports strict mode and data objects.
7
+ * The function allows the dynamic execution of code with optional binding of the provided data to the function context.
8
+ * If `splitData` is true, the data is split into keys and values for parameterized function execution.
9
+ * This function dynamically generates and executes a new function based on the provided content.
10
+ *
11
+ * @param {string} content - The JavaScript code as a string to execute. This code can contain variables that will be replaced with data values.
12
+ * @param {object|array} data - The data object or array to bind to the code. This is used to replace placeholders or reference `this` inside the code.
13
+ * @param {boolean} [splitData=false] - Whether to split the data into keys and values. If true, the `data` object is converted into individual parameters.
14
+ * @returns {any} - The result of the executed code. This could be any type depending on the content of the code being executed.
15
+ *
16
+ */
17
+ const executeStr = (content: string, data: any, splitData: boolean = false): any => {
18
+ //content要求是字符串格式
19
+ requireTypes(content, 'string', (error) => {
20
+ console.error(error);
21
+ return;
22
+ });
23
+ let dataType = requireTypes(data, ['array', 'object'], (error) => {
24
+ console.error(error);
25
+ return;
26
+ }),
27
+ result;
28
+
29
+ if (splitData && dataType === 'Object') {
30
+ let keys = Object.keys(data),
31
+ values = Object.values(data),
32
+ tmp = new Function(...keys, content).bind(data);
33
+ result = tmp(...values);
34
+ } else {
35
+ const tmp = new Function(content).apply(data);
36
+ result = tmp();
37
+ }
38
+
39
+ return result;
40
+ }
41
+
42
+ export default executeStr;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @since Last modified: 2025/12/16 09:00:41
3
+ * @function getDataType
4
+ * @description Get object type.Can detect object types such as Array, Object, Function,
5
+ * Window,Location,History,Navigator,XMLHttpRequest, WebSocket,FileReader,MediaStream
6
+ * Class , String, Number, Boolean, Date, Symbol ,File ,Blob,
7
+ * Error,Promise,ArrayBuffer,TypedArray, Set, weakSet, Map, weakMap, Null, Undefined,
8
+ * Text, DocumentFragment,Comment, XMLDocument, ProcessingInstruction, Range, TreeWalker,
9
+ * NodeIterator,SVGSVGElement,MathMLElement, HTMLxxxElement (Dom nodes all contain HTML),Promise,AsyncFunction and Instance.
10
+ * @param {*} obj - Can be any object
11
+ * @returns {string} - Returns the name of the data type.
12
+ */
13
+ 'use strict';
14
+ const getDataType = (obj) => {
15
+ let tmp = Object.prototype.toString.call(obj).slice(8, -1), result;
16
+ if (tmp === 'Function' && /^\s*class\s+/.test(obj.toString())) {
17
+ result = 'Class';
18
+ }
19
+ else if (tmp === 'Object' && Object.getPrototypeOf(obj) !== Object.prototype) {
20
+ result = 'Instance';
21
+ }
22
+ else {
23
+ result = tmp;
24
+ }
25
+ return result;
26
+ //document.createElement -> HTMLxxxElement
27
+ //document.createDocumentFragment() -> DocumentFragment
28
+ //document.createComment() -> Comment
29
+ //document.createTextNode -> Text
30
+ //document.createCDATASection() -> XMLDocument
31
+ //document.createProcessingInstruction() -> ProcessingInstruction
32
+ //document.createRange() -> Range
33
+ //document.createTreeWalker() -> TreeWalker
34
+ //document.createNodeIterator() -> NodeIterator
35
+ //document.createElementNS('http://www.w3.org/2000/svg', 'svg'); -> SVGSVGElement
36
+ //document.createElementNS('http://www.w3.org/1998/Math/MathML', 'math'); -> MathMLElement
37
+ };
38
+ export default getDataType;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @since Last modified: 2025/12/16 09:00:41
3
+ * @function getDataType
4
+ * @description Get object type.Can detect object types such as Array, Object, Function,
5
+ * Window,Location,History,Navigator,XMLHttpRequest, WebSocket,FileReader,MediaStream
6
+ * Class , String, Number, Boolean, Date, Symbol ,File ,Blob,
7
+ * Error,Promise,ArrayBuffer,TypedArray, Set, weakSet, Map, weakMap, Null, Undefined,
8
+ * Text, DocumentFragment,Comment, XMLDocument, ProcessingInstruction, Range, TreeWalker,
9
+ * NodeIterator,SVGSVGElement,MathMLElement, HTMLxxxElement (Dom nodes all contain HTML),Promise,AsyncFunction and Instance.
10
+ * @param {*} obj - Can be any object
11
+ * @returns {string} - Returns the name of the data type.
12
+ */
13
+ 'use strict';
14
+ const getDataType = (obj: any): string => {
15
+ let tmp = Object.prototype.toString.call(obj).slice(8, -1),
16
+ result;
17
+ if (tmp === 'Function' && /^\s*class\s+/.test(obj.toString())) {
18
+ result = 'Class';
19
+ } else if (tmp === 'Object' && Object.getPrototypeOf(obj) !== Object.prototype) {
20
+ result = 'Instance';
21
+ } else {
22
+ result = tmp;
23
+ }
24
+ return result;
25
+ //document.createElement -> HTMLxxxElement
26
+ //document.createDocumentFragment() -> DocumentFragment
27
+ //document.createComment() -> Comment
28
+ //document.createTextNode -> Text
29
+ //document.createCDATASection() -> XMLDocument
30
+ //document.createProcessingInstruction() -> ProcessingInstruction
31
+ //document.createRange() -> Range
32
+ //document.createTreeWalker() -> TreeWalker
33
+ //document.createNodeIterator() -> NodeIterator
34
+ //document.createElementNS('http://www.w3.org/2000/svg', 'svg'); -> SVGSVGElement
35
+ //document.createElementNS('http://www.w3.org/1998/Math/MathML', 'math'); -> MathMLElement
36
+ };
37
+ export default getDataType;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @since Last modified: 2025/11/15 16:52:18
3
+ * @function parseStr
4
+ * @description Safely parses a string content and evaluates it based on the provided method.
5
+ * This function allows parsing content as JSON, or using custom evaluation via the provided method,
6
+ * with the ability to bind a custom context (`this`) during evaluation.
7
+ *
8
+ * @param {object} options - The options for parsing the string.
9
+ * @param {string | null} options.content - The string content to be parsed. (required)
10
+ * @param {('new Function' | 'JSON.parse' | T_fn)} [options.method='new Function'] - The method to use for parsing.
11
+ * @param {boolean} [options.catchable=false] - Whether to throw an error on failure or return an empty value.
12
+ * @param {boolean} [options.safe=false] - Whether to escape HTML characters to prevent XSS attacks.
13
+ * @param {any} [options.bind] - The context (`this`) to bind during evaluation.
14
+ * @param {T_fn} [options.error] - The callback function to call when an error occurs.
15
+ * @returns {any} The parsed result.
16
+ */
17
+ 'use strict';
18
+ import { escapeHTML } from "./escapeHTML";
19
+ import requireTypes from "./requireTypes";
20
+ const parseStr = ({ content = '', method = 'new Function', catchable = false, safe = false, bind, error }) => {
21
+ //必须是字符串格式
22
+ requireTypes(content, 'String', (error) => {
23
+ console.error(error);
24
+ return null;
25
+ });
26
+ let result, trim = content?.trim();
27
+ if (!trim)
28
+ return '';
29
+ //防止注入攻击,则过滤文本
30
+ safe && (trim = escapeHTML(trim));
31
+ try {
32
+ //method可能是一个函数
33
+ result = typeof method === 'function' ? method(trim) :
34
+ method === 'JSON.parse' ? JSON.parse(trim) :
35
+ //允许绑定this,也就是说content中可以使用this关键字
36
+ (bind ? new Function(`"use strict"; return ${trim}`).apply(bind) : new Function(`"use strict"; return ${trim}`)());
37
+ }
38
+ catch (err) {
39
+ error && error(err);
40
+ //如果抛出错误则会阻止执行,不会返回result
41
+ if (catchable)
42
+ throw err;
43
+ }
44
+ return result;
45
+ };
46
+ export default parseStr;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @since Last modified: 2025/11/15 16:52:18
3
+ * @function parseStr
4
+ * @description Safely parses a string content and evaluates it based on the provided method.
5
+ * This function allows parsing content as JSON, or using custom evaluation via the provided method,
6
+ * with the ability to bind a custom context (`this`) during evaluation.
7
+ *
8
+ * @param {object} options - The options for parsing the string.
9
+ * @param {string | null} options.content - The string content to be parsed. (required)
10
+ * @param {('new Function' | 'JSON.parse' | T_fn)} [options.method='new Function'] - The method to use for parsing.
11
+ * @param {boolean} [options.catchable=false] - Whether to throw an error on failure or return an empty value.
12
+ * @param {boolean} [options.safe=false] - Whether to escape HTML characters to prevent XSS attacks.
13
+ * @param {any} [options.bind] - The context (`this`) to bind during evaluation.
14
+ * @param {T_fn} [options.error] - The callback function to call when an error occurs.
15
+ * @returns {any} The parsed result.
16
+ */
17
+ 'use strict';
18
+ import { T_fn, T_null, T_obj } from "../types/utils";
19
+ import { escapeHTML } from "./escapeHTML";
20
+ import requireTypes from "./requireTypes";
21
+ const parseStr = ({ content = '', method = 'new Function', catchable = false, safe = false, bind, error }: { content: string | T_null, method?: 'new Function' | 'JSON.parse' | T_fn, catchable?: boolean, safe?: boolean, bind?: any, error?: T_fn }) => {
22
+
23
+ //必须是字符串格式
24
+ requireTypes(content, 'String', (error) => {
25
+ console.error(error);
26
+ return null;
27
+ });
28
+ let result,
29
+ trim = content?.trim();
30
+ if (!trim) return '';
31
+ //防止注入攻击,则过滤文本
32
+ safe && (trim = escapeHTML(trim));
33
+
34
+ try {
35
+ //method可能是一个函数
36
+ result = typeof method === 'function' ? method(trim) :
37
+ method === 'JSON.parse' ? JSON.parse(trim) :
38
+ //允许绑定this,也就是说content中可以使用this关键字
39
+ (bind ? new Function(`"use strict"; return ${trim}`).apply(bind) : new Function(`"use strict"; return ${trim}`)());
40
+ } catch (err) {
41
+ error && error(err);
42
+ //如果抛出错误则会阻止执行,不会返回result
43
+ if (catchable) throw err;
44
+ }
45
+ return result;
46
+ };
47
+ export default parseStr;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * @since Last modified: 2025/11/15 16:24:20
3
+ * @function renderTpl
4
+ * @description Get template string through parameters.Cut the template strings into fragments through labels, and put into the array through the PUSH method, and finally merge into a new string.
5
+ * @param {string} html - Text string with variables, for example: html=`I like {{this.name}}, she is {{this.age}} years old`.
6
+ * @param {object|array} data - Variable key-value pairs, for example: data={name:'Lily',age:20} or [{name:'Lily'},{name:'Mark'}].
7
+ * @param {Object} [options] - Configuration options to control the rendering behavior:
8
+ * @param {boolean} [options.safe=false] - If true, HTML special characters in the template will be escaped to prevent XSS attacks. Default is `false`.
9
+ * @param {boolean} [options.strict=false] - If true, the template engine will require using `this` to access properties, especially for arrays. Default is `false`.
10
+ * @param {string} [options.start='{{'] - The opening delimiter for template variables. Default is `{{`.
11
+ * @param {string} [options.end='}}'] - The closing delimiter for template variables. Default is `}}`.
12
+ * @param {string} [options.suffix='/'] - The suffix for ending script-like expressions. Default is `/`. This is used to close template expressions like `{{this.fn() /}}`.
13
+ * @returns {string} - The string after the variables are replaced with data.
14
+ */
15
+ 'use strict';
16
+ import { escapeHTML } from "./escapeHTML";
17
+ import requireTypes from "./requireTypes";
18
+ const renderTpl = (html, data, options = {}) => {
19
+ requireTypes(html, 'string', (error) => {
20
+ //不符合要求的类型
21
+ console.error(error);
22
+ return '';
23
+ });
24
+ if (!html.trim())
25
+ return '';
26
+ let dataType = requireTypes(data, ['array', 'object'], (error) => {
27
+ //不符合要求的类型
28
+ console.error(error);
29
+ return html;
30
+ });
31
+ //data={}/[]
32
+ if (Object.keys(data).length === 0) {
33
+ console.warn('Data is empty ({}/[]), no rendering performed, original text outputted.');
34
+ return html;
35
+ }
36
+ let opts = Object.assign({ safe: false, strict: false, start: '{{', end: '}}', suffix: '/' }, options), tplStr = opts.safe ? escapeHTML(html) : html,
37
+ //regStart='\\{\\{'
38
+ regStart = opts.start.split('').map(k => '\\' + k).join(''),
39
+ //regEnd='\\}\\}'
40
+ regEnd = opts.end.split('').map(k => '\\' + k).join(''), tplReg = new RegExp(`${regStart}([\\s\\S]+?)?${regEnd}`, 'g'), code = '"use strict";let str=[];\n', cursor = 0, match, result = '', add = (fragment, isScript) => {
41
+ isScript ? (code += (fragment.endsWith(opts.suffix) ? fragment.replace('=&gt;', '=>').slice(0, -1) + '\n' : 'str.push(' + fragment + ');\n'))
42
+ : (code += (fragment !== '' ? 'str.push("' + fragment.replace(/"/g, '\\"') + '");\n' : ''));
43
+ return add;
44
+ };
45
+ while (match = tplReg.exec(tplStr)) {
46
+ add(tplStr.slice(cursor, match.index))(match[1], true);
47
+ cursor = match.index + match[0].length;
48
+ }
49
+ add(tplStr.slice(cursor));
50
+ code += `return str.join('');`;
51
+ try {
52
+ if (opts.strict || dataType === 'Array') {
53
+ //严格模式,或者是数组数据,则必须使用this
54
+ result = new Function(code.replace(/[\r\t\n]/g, '')).apply(data);
55
+ }
56
+ else {
57
+ ////非严格模式,且是对象,则可省略this
58
+ let keys = Object.keys(data), values = Object.values(data),
59
+ //keys传参,this依然可指向data
60
+ tmp = new Function(...keys, code.replace(/[\r\t\n]/g, '')).bind(data);
61
+ //执行时以value赋值
62
+ result = tmp(...values);
63
+ }
64
+ }
65
+ catch (err) {
66
+ console.error(`'${err.message}'`, ' in \n', code, '\n');
67
+ }
68
+ return result;
69
+ };
70
+ export default renderTpl;