funda-ui 4.7.604 → 4.7.608
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/Chatbox/index.js +123 -69
- package/LiveSearch/index.js +117 -67
- package/MultipleCheckboxes/index.js +117 -67
- package/MultipleSelect/index.js +117 -67
- package/NativeSelect/index.js +117 -67
- package/Radio/index.js +117 -67
- package/Select/index.js +117 -67
- package/Utils/anim.js +116 -62
- package/Utils/initDefaultOptions.js +116 -62
- package/Utils/validate.d.ts +1 -7
- package/Utils/validate.js +115 -62
- package/lib/cjs/Chatbox/index.js +123 -69
- package/lib/cjs/LiveSearch/index.js +117 -67
- package/lib/cjs/MultipleCheckboxes/index.js +117 -67
- package/lib/cjs/MultipleSelect/index.js +117 -67
- package/lib/cjs/NativeSelect/index.js +117 -67
- package/lib/cjs/Radio/index.js +117 -67
- package/lib/cjs/Select/index.js +117 -67
- package/lib/cjs/Utils/anim.js +116 -62
- package/lib/cjs/Utils/initDefaultOptions.js +116 -62
- package/lib/cjs/Utils/validate.d.ts +1 -7
- package/lib/cjs/Utils/validate.js +115 -62
- package/lib/esm/Chatbox/index.tsx +8 -2
- package/lib/esm/Utils/libs/validate.ts +167 -194
- package/package.json +1 -1
|
@@ -1,73 +1,85 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Fix And Parse JSON (Support for handling complex escape JSON strings)
|
|
3
|
+
* @desc recursively fix top-level key/value (recursively handles when encountering top-level values that are objects/arrays)
|
|
3
4
|
* @private
|
|
4
5
|
*/
|
|
5
6
|
/*
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
- Then process the outermost object or array key
|
|
9
|
-
- If a top-level value is an unquoted object or array (e.g
|
|
10
|
-
|
|
11
|
-
- For values wrapped in quotes ('...' or "..."), extract the inner text and
|
|
12
|
-
re-encode it using JSON.stringify (ensures internal single/double quotes
|
|
13
|
-
are not corrupted);
|
|
7
|
+
- Still prioritize JSON.parse first;
|
|
8
|
+
- After parse fails, do unescaping (\\" → ");
|
|
9
|
+
- Then process the outermost layer (object or array) key by key, value by value;
|
|
10
|
+
- If a top-level value is an unquoted object or array (e.g., messages: [ {...} ]), recursively treat that value as a new outermost layer for fixing;
|
|
11
|
+
- For strings wrapped in quotes ('...' or "..."), only extract the outer layer and re-encode with JSON.stringify (ensuring internal single/double quotes won't be mistakenly changed);
|
|
14
12
|
- Set MAX_DEPTH to prevent infinite recursion.
|
|
15
13
|
*/
|
|
16
|
-
// fixAndParseJSON - recursively repairs top-level key/value
|
|
17
|
-
// (when encountering outermost values that are objects/arrays, it recurses)
|
|
18
|
-
|
|
19
|
-
interface ParseResult {
|
|
20
|
-
success: boolean;
|
|
21
|
-
data?: any;
|
|
22
|
-
error?: string;
|
|
23
|
-
details?: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
type JSONValue = string | number | boolean | null | JSONObject | JSONArray;
|
|
27
|
-
interface JSONObject {
|
|
28
|
-
[key: string]: JSONValue;
|
|
29
|
-
}
|
|
30
|
-
interface JSONArray extends Array<JSONValue> {}
|
|
31
|
-
|
|
32
14
|
/*
|
|
33
|
-
|
|
15
|
+
@Examples:
|
|
34
16
|
|
|
35
|
-
// ✅ Valid JSON (contains svg and single
|
|
17
|
+
// ✅ Valid JSON (contains svg and single quote content)
|
|
36
18
|
const okJson = `{
|
|
37
|
-
"label":"<svg width='16' height='16'><path fill='currentColor' d='M19 13h-6'/></svg>
|
|
19
|
+
"label":"<svg width='16' height='16'><path fill='currentColor' d='M19 13h-6'/></svg> 新建会话",
|
|
38
20
|
"value":"new",
|
|
39
21
|
"onClick":"method.setVal(''); method.clearData();"
|
|
40
22
|
}`;
|
|
41
23
|
|
|
42
|
-
|
|
24
|
+
const okJson2 = `{
|
|
25
|
+
label:"<svg width='16' height='16'><path fill='currentColor' d='M19 13h-6'/></svg> 新建会话",
|
|
26
|
+
value:"new",
|
|
27
|
+
onClick:"method.setVal(''); method.clearData();"
|
|
28
|
+
}`;
|
|
29
|
+
|
|
30
|
+
// ⚠️ Single quote JSON
|
|
43
31
|
const badJson = "{'model':'{model}','messages':[{'role':'user','content':'{message}'}],'stream': true}";
|
|
44
32
|
|
|
45
|
-
//
|
|
46
|
-
const badJson2 = "{\\\"label\\\":\\\"<svg width='16' height='16' viewBox='0 0 24 24'><path fill='currentColor' d='M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z'/></svg>
|
|
33
|
+
// ⚠️ Escaped JSON
|
|
34
|
+
const badJson2 = "{\\\"label\\\":\\\"<svg width='16' height='16' viewBox='0 0 24 24'><path fill='currentColor' d='M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z'/></svg> 新建会话\\\",\\\"value\\\":\\\"new\\\",\\\"onClick\\\":\\\"method.setVal(''); method.clearData();\\\"}";
|
|
35
|
+
|
|
36
|
+
const badJson3 = "{\"label\":\"<svg width='16' height='16' viewBox='0 0 24 24'><path fill='currentColor' d='M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z'/></svg> 新建会话\",\"value\":\"new\",\"onClick\":\"method.setVal(''); method.clearData();\"}";
|
|
37
|
+
|
|
38
|
+
const badJson4 = "[{\"label\":\"<svg fill='currentColor' width='12' height='12' viewBox='0 0 24 24'><path d='M20.5 9a3.49 3.49 0 0 0-3.45 3h-1.1a2.49 2.49 0 0 0-4.396-1.052L8.878 9.731l3.143-4.225a2.458 2.458 0 0 0 2.98-.019L17.339 8H16v1h3V6h-1v1.243l-2.336-2.512A2.473 2.473 0 0 0 16 3.5a2.5 2.5 0 0 0-5 0 2.474 2.474 0 0 0 .343 1.243L7.947 9.308 4.955 7.947a2.404 2.404 0 0 0-.161-1.438l3.704-1.385-.44 1.371.942.333L10 4 7.172 3l-.334.943 1.01.357-3.659 1.368a2.498 2.498 0 1 0-.682 4.117l2.085 2.688-2.053 2.76a2.5 2.5 0 1 0 .87 3.864l3.484 1.587-1.055.373.334.943L10 21l-1-2.828-.943.333.435 1.354-3.608-1.645A2.471 2.471 0 0 0 5 17.5a2.5 2.5 0 0 0-.058-.527l3.053-1.405 3.476 4.48a2.498 2.498 0 1 0 4.113.075L18 17.707V19h1v-3h-3v1h1.293l-2.416 2.416a2.466 2.466 0 0 0-2.667-.047l-3.283-4.23 2.554-1.176A2.494 2.494 0 0 0 15.95 13h1.1a3.493 3.493 0 1 0 3.45-4zm-7-7A1.5 1.5 0 1 1 12 3.5 1.502 1.502 0 0 1 13.5 2zm0 18a1.5 1.5 0 1 1-1.5 1.5 1.502 1.502 0 0 1 1.5-1.5zM1 7.5a1.5 1.5 0 1 1 2.457 1.145l-.144.112A1.496 1.496 0 0 1 1 7.5zm3.32 1.703a2.507 2.507 0 0 0 .264-.326l2.752 1.251-1.124 1.512zM2.5 19A1.5 1.5 0 1 1 4 17.5 1.502 1.502 0 0 1 2.5 19zm2.037-2.941a2.518 2.518 0 0 0-.193-.234l1.885-2.532 1.136 1.464zm3.76-1.731L6.849 12.46l1.42-1.908L11.1 11.84a2.29 2.29 0 0 0-.033 1.213zM13.5 14a1.5 1.5 0 1 1 1.5-1.5 1.502 1.502 0 0 1-1.5 1.5zm7 1a2.5 2.5 0 1 1 2.5-2.5 2.502 2.502 0 0 1-2.5 2.5zm1.5-2.5a1.5 1.5 0 1 1-1.5-1.5 1.502 1.502 0 0 1 1.5 1.5z'/><path fill='none' d='M0 0h24v24H0z'/></svg> 深度思考\",\"value\":\"brief\",\"onClick\":\"if(isActive){method.executeCustomMethod('changeModel', true)}else{method.executeCustomMethod('changeModel', false)}\"},{\"label\":\"<svg fill='currentColor' width='12' height='12' viewBox='0 0 24 24'><path d='M19 2H5c-1.103 0-2 .897-2 2v12c0 1.103.897 2 2 2h3.586L12 21.414 15.414 18H19c1.103 0 2-.897 2-2V4c0-1.103-.897-2-2-2zm0 14h-4.414L12 18.586 9.414 16H5V4h14v12z'/></svg> 精简回答\",\"value\":\"brief\",\"onClick\":\"if(isActive){method.setContextData({systemPrompt:'请精简回答,字数控制在150个字左右, 思考过程请简洁简短',mergedText:method.getContextData().mergedText,analyzeMetrics:method.getContextData().analyzeMetrics});}else{method.setContextData({mergedText:method.getContextData().mergedText,analyzeMetrics:method.getContextData().analyzeMetrics});}\"},{\"label\":\"<svg fill='none' width='12' height='12' viewBox='0 0 16 16'><path d='M7 0.0618896V9H15.9381C15.446 12.9463 12.0796 16 8 16C3.58172 16 0 12.4183 0 8C0 3.92038 3.05369 0.553988 7 0.0618896Z' fill='currentColor'/><path d='M9 0.0618897V7H15.9381C15.4869 3.38128 12.6187 0.513137 9 0.0618897Z' fill='currentColor'/></svg> 指标分析\",\"value\":\"lab\",\"onClick\":\"return method.executeCustomMethod('getLibList')\",\"isSelect\":true,\"dynamicOptions\":true}]";
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
// ❌ Invalid JSON with missing } or ]
|
|
42
|
+
const errorJson001 = "{'model':'qwen-plus','base_url':'https://dashscope.aliyuncs.com/compatible-mode/v1/','api_key':'sk-0989fb9baab8450682af4d000f5b7cba','message':'{message}','stream':'true','chatId': '{chatId}', 'token': '{token}'";
|
|
43
|
+
|
|
44
|
+
const errorJson002 = "[{'model':'qwen-plus','base_url':'https://dashscope.aliyuncs.com/compatible-mode/v1/','api_key':'sk-0989fb9baab8450682af4d000f5b7cba','message':'{message}','stream':'true','chatId': '{chatId}', 'token': '{token}'}";
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
// ❌ Invalid JSON with missing quotes
|
|
47
|
+
const errorJson003 = "{'model':'qwen-plus','base_url':'https://dashscope.aliyuncs.com/compatible-mode/v1/','api_key':'sk-0989fb9baab8450682af4d000f5b7cba','message':'{message}','stream':'true','chatId': {chatId}', 'token': '{token}'}";
|
|
49
48
|
|
|
50
|
-
const badJson4 = "[{\"label\":\"<svg fill='currentColor' width='12' height='12' viewBox='0 0 24 24'><path d='M20.5 9a3.49 3.49 0 0 0-3.45 3h-1.1a2.49 2.49 0 0 0-4.396-1.052L8.878 9.731l3.143-4.225a2.458 2.458 0 0 0 2.98-.019L17.339 8H16v1h3V6h-1v1.243l-2.336-2.512A2.473 2.473 0 0 0 16 3.5a2.5 2.5 0 0 0-5 0 2.474 2.474 0 0 0 .343 1.243L7.947 9.308 4.955 7.947a2.404 2.404 0 0 0-.161-1.438l3.704-1.385-.44 1.371.942.333L10 4 7.172 3l-.334.943 1.01.357-3.659 1.368a2.498 2.498 0 1 0-.682 4.117l2.085 2.688-2.053 2.76a2.5 2.5 0 1 0 .87 3.864l3.484 1.587-1.055.373.334.943L10 21l-1-2.828-.943.333.435 1.354-3.608-1.645A2.471 2.471 0 0 0 5 17.5a2.5 2.5 0 0 0-.058-.527l3.053-1.405 3.476 4.48a2.498 2.498 0 1 0 4.113.075L18 17.707V19h1v-3h-3v1h1.293l-2.416 2.416a2.466 2.466 0 0 0-2.667-.047l-3.283-4.23 2.554-1.176A2.494 2.494 0 0 0 15.95 13h1.1a3.493 3.493 0 1 0 3.45-4zm-7-7A1.5 1.5 0 1 1 12 3.5 1.502 1.502 0 0 1 13.5 2zm0 18a1.5 1.5 0 1 1-1.5 1.5 1.502 1.502 0 0 1 1.5-1.5zM1 7.5a1.5 1.5 0 1 1 2.457 1.145l-.144.112A1.496 1.496 0 0 1 1 7.5zm3.32 1.703a2.507 2.507 0 0 0 .264-.326l2.752 1.251-1.124 1.512zM2.5 19A1.5 1.5 0 1 1 4 17.5 1.502 1.502 0 0 1 2.5 19zm2.037-2.941a2.518 2.518 0 0 0-.193-.234l1.885-2.532 1.136 1.464zm3.76-1.731L6.849 12.46l1.42-1.908L11.1 11.84a2.29 2.29 0 0 0-.033 1.213zM13.5 14a1.5 1.5 0 1 1 1.5-1.5 1.502 1.502 0 0 1-1.5 1.5zm7 1a2.5 2.5 0 1 1 2.5-2.5 2.502 2.502 0 0 1-2.5 2.5zm1.5-2.5a1.5 1.5 0 1 1-1.5-1.5 1.502 1.502 0 0 1 1.5 1.5z'/><path fill='none' d='M0 0h24v24H0z'/></svg> Deep Thought","value":"brief","onClick":"if(isActive){method.executeCustomMethod('changeModel', true)}else{method.executeCustomMethod('changeModel', false)}"},{"label":"<svg fill='currentColor' width='12' height='12' viewBox='0 0 24 24'><path d='M19 2H5c-1.103 0-2 .897-2 2v12c0 1.103.897 2 2 2h3.586L12 21.414 15.414 18H19c1.103 0 2-.897 2-2V4c0-1.103-.897-2-2-2zm0 14h-4.414L12 18.586 9.414 16H5V4h14v12z'/></svg> Concise Answer","value":"brief","onClick":"if(isActive){method.setContextData({systemPrompt:'Please answer concisely, around 150 words, keep reasoning brief',mergedText:method.getContextData().mergedText,analyzeMetrics:method.getContextData().analyzeMetrics});}else{method.setContextData({mergedText:method.getContextData().mergedText,analyzeMetrics:method.getContextData().analyzeMetrics});}"},{"label":"<svg fill='none' width='12' height='12' viewBox='0 0 16 16'><path d='M7 0.0618896V9H15.9381C15.446 12.9463 12.0796 16 8 16C3.58172 16 0 12.4183 0 8C0 3.92038 3.05369 0.553988 7 0.0618896Z' fill='currentColor'/><path d='M9 0.0618897V7H15.9381C15.4869 3.38128 12.6187 0.513137 9 0.0618897Z' fill='currentColor'/></svg> Metrics Analysis","value":"lab","onClick":"return method.executeCustomMethod('getLibList')","isSelect":true,"dynamicOptions":true}]";
|
|
51
49
|
|
|
52
50
|
|
|
53
|
-
console.log('okJson =>', fixAndParseJSON(okJson));
|
|
54
|
-
console.log('
|
|
55
|
-
console.log('
|
|
56
|
-
console.log('
|
|
57
|
-
console.log('
|
|
51
|
+
console.log('okJson =>', fixAndParseJSON(okJson)); // Can parse normally success = true
|
|
52
|
+
console.log('okJson =>', fixAndParseJSON(okJson2)); // Can parse normally success = true
|
|
53
|
+
console.log('badJson =>', fixAndParseJSON(badJson)); // Can parse after fixing success = true
|
|
54
|
+
console.log('badJson =>', fixAndParseJSON(badJson2)); // Can parse after fixing success = true
|
|
55
|
+
console.log('badJson =>', fixAndParseJSON(badJson3)); // Can parse after fixing success = true
|
|
56
|
+
console.log('badJson =>', fixAndParseJSON(badJson4)); // Can parse after fixing success = true
|
|
57
|
+
console.log('errorJson =>', fixAndParseJSON(errorJson001)); // {success: false, error: 'Invalid JSON format', details: 'Invalid object: mismatched braces'}
|
|
58
|
+
console.log('errorJson =>', fixAndParseJSON(errorJson002)); // {success: false, error: 'Invalid JSON format', details: "Expected property name or '}' in JSON at position 2 (line 1 column 3)"}
|
|
59
|
+
console.log('errorJson =>', fixAndParseJSON(errorJson003)); // {success: false, error: 'Invalid JSON format', details: 'Invalid object: mismatched braces'}
|
|
60
|
+
|
|
58
61
|
*/
|
|
59
|
-
|
|
62
|
+
|
|
63
|
+
// Type definitions
|
|
64
|
+
interface ParseResult {
|
|
65
|
+
success: boolean;
|
|
66
|
+
data?: any;
|
|
67
|
+
error?: string;
|
|
68
|
+
details?: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function fixAndParseJSON(input: string): ParseResult {
|
|
60
72
|
const MAX_DEPTH = 6;
|
|
61
73
|
|
|
62
|
-
// 1.
|
|
74
|
+
// 1. Quick attempt
|
|
63
75
|
try {
|
|
64
76
|
return { success: true, data: JSON.parse(input) };
|
|
65
77
|
} catch (e) {
|
|
66
|
-
//
|
|
78
|
+
// Continue with fixing
|
|
67
79
|
}
|
|
68
80
|
|
|
69
|
-
// 2. Simple
|
|
70
|
-
let s
|
|
81
|
+
// 2. Simple unescaping of escaped \" (common case from pasted JS literals)
|
|
82
|
+
let s = input;
|
|
71
83
|
if (s.includes('\\"')) s = s.replace(/\\"/g, '"');
|
|
72
84
|
s = s.trim();
|
|
73
85
|
|
|
@@ -82,42 +94,75 @@ export function fixAndParseJSON(input: string): ParseResult {
|
|
|
82
94
|
|
|
83
95
|
return { success: true, data: JSON.parse(s) };
|
|
84
96
|
} catch (err) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
error: 'Invalid JSON format',
|
|
88
|
-
details: err instanceof Error ? err.message : String(err)
|
|
89
|
-
};
|
|
97
|
+
const error = err instanceof Error ? err : new Error('Unknown error');
|
|
98
|
+
return { success: false, error: 'Invalid JSON format', details: error.message };
|
|
90
99
|
}
|
|
91
100
|
}
|
|
92
101
|
|
|
93
|
-
/* ---------- Helper (
|
|
102
|
+
/* ---------- Helper (Recursive) Functions ---------- */
|
|
94
103
|
|
|
95
104
|
function processTopObject(str: string, depth: number, MAX_DEPTH: number): string {
|
|
96
105
|
if (depth > MAX_DEPTH) return str;
|
|
97
106
|
str = str.trim();
|
|
98
|
-
|
|
107
|
+
|
|
108
|
+
// First check if braces match
|
|
109
|
+
let braceCount = 0;
|
|
110
|
+
let inString = false;
|
|
111
|
+
let escapeNext = false;
|
|
112
|
+
|
|
113
|
+
for (let i = 0; i < str.length; i++) {
|
|
114
|
+
const ch = str[i];
|
|
115
|
+
|
|
116
|
+
if (escapeNext) {
|
|
117
|
+
escapeNext = false;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (ch === '\\') {
|
|
122
|
+
escapeNext = true;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if ((ch === '"' || ch === "'") && !escapeNext) {
|
|
127
|
+
inString = !inString;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!inString) {
|
|
132
|
+
if (ch === '{') braceCount++;
|
|
133
|
+
else if (ch === '}') braceCount--;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (braceCount !== 0) {
|
|
138
|
+
throw new Error('Invalid object: mismatched braces');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Ensure both ends are { ... }
|
|
99
142
|
if (!(str.startsWith('{') && str.endsWith('}'))) {
|
|
100
|
-
const f
|
|
101
|
-
|
|
102
|
-
|
|
143
|
+
const f = str.indexOf('{'), l = str.lastIndexOf('}');
|
|
144
|
+
if (f === -1 || l === -1 || l <= f) {
|
|
145
|
+
throw new Error('Invalid object format: missing or mismatched braces');
|
|
146
|
+
}
|
|
103
147
|
str = str.slice(f, l + 1);
|
|
104
148
|
}
|
|
105
|
-
|
|
106
|
-
const
|
|
149
|
+
|
|
150
|
+
const inner = str.slice(1, -1);
|
|
151
|
+
const pairs = splitTopLevel(inner);
|
|
107
152
|
|
|
108
|
-
const repairedPairs
|
|
153
|
+
const repairedPairs = pairs.map(pair => {
|
|
109
154
|
if (!pair || pair.trim() === '') return '';
|
|
110
|
-
const idx
|
|
155
|
+
const idx = findTopLevelColon(pair);
|
|
111
156
|
if (idx === -1) {
|
|
112
157
|
return pair; // Non key:value fragment, keep as is (rare case)
|
|
113
158
|
}
|
|
114
|
-
const rawKey
|
|
115
|
-
const rawVal
|
|
159
|
+
const rawKey = pair.slice(0, idx).trim();
|
|
160
|
+
const rawVal = pair.slice(idx + 1);
|
|
116
161
|
|
|
117
|
-
const keyContent
|
|
118
|
-
const keyJson
|
|
162
|
+
const keyContent = extractKeyContent(rawKey);
|
|
163
|
+
const keyJson = JSON.stringify(keyContent);
|
|
119
164
|
|
|
120
|
-
const repairedValue
|
|
165
|
+
const repairedValue = repairPossiblyQuotedValue(rawVal, depth + 1, MAX_DEPTH);
|
|
121
166
|
|
|
122
167
|
return keyJson + ':' + repairedValue;
|
|
123
168
|
});
|
|
@@ -129,16 +174,15 @@ function processTopArray(str: string, depth: number, MAX_DEPTH: number): string
|
|
|
129
174
|
if (depth > MAX_DEPTH) return str;
|
|
130
175
|
str = str.trim();
|
|
131
176
|
if (!(str.startsWith('[') && str.endsWith(']'))) {
|
|
132
|
-
const f
|
|
133
|
-
const l: number = str.lastIndexOf(']');
|
|
177
|
+
const f = str.indexOf('['), l = str.lastIndexOf(']');
|
|
134
178
|
if (f === -1 || l === -1 || l <= f) return str;
|
|
135
179
|
str = str.slice(f, l + 1);
|
|
136
180
|
}
|
|
137
|
-
const inner
|
|
138
|
-
const elements
|
|
181
|
+
const inner = str.slice(1, -1);
|
|
182
|
+
const elements = splitTopLevel(inner);
|
|
139
183
|
|
|
140
|
-
const processed
|
|
141
|
-
const t
|
|
184
|
+
const processed = elements.map(el => {
|
|
185
|
+
const t = el.trim();
|
|
142
186
|
if (t === '') return '';
|
|
143
187
|
if (t.startsWith('{')) return processTopObject(t, depth + 1, MAX_DEPTH);
|
|
144
188
|
if (t.startsWith('[')) return processTopArray(t, depth + 1, MAX_DEPTH);
|
|
@@ -148,37 +192,30 @@ function processTopArray(str: string, depth: number, MAX_DEPTH: number): string
|
|
|
148
192
|
return '[' + processed.join(',') + ']';
|
|
149
193
|
}
|
|
150
194
|
|
|
151
|
-
// If
|
|
152
|
-
// If
|
|
153
|
-
// Otherwise return
|
|
195
|
+
// If it's a string wrapped in quotes, extract the inner content and JSON.stringify (safe escaping)
|
|
196
|
+
// If it's an object/array literal (not wrapped in quotes), recursively process (treat as new outermost layer)
|
|
197
|
+
// Otherwise return the original fragment directly (numbers/true/false/null or JS expressions)
|
|
154
198
|
function repairPossiblyQuotedValue(rawVal: string, depth: number, MAX_DEPTH: number): string {
|
|
155
|
-
const v
|
|
199
|
+
const v = rawVal.trim();
|
|
156
200
|
if (v === '') return v;
|
|
157
201
|
|
|
158
202
|
if (v[0] === '"' || v[0] === "'") {
|
|
159
|
-
const quote
|
|
160
|
-
// Find the last unescaped
|
|
161
|
-
let lastPos
|
|
162
|
-
for (let i
|
|
203
|
+
const quote = v[0];
|
|
204
|
+
// Find the last unescaped same quote
|
|
205
|
+
let lastPos = -1;
|
|
206
|
+
for (let i = v.length - 1; i >= 0; i--) {
|
|
163
207
|
if (v[i] === quote) {
|
|
164
|
-
// check
|
|
165
|
-
let bs
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
bs++;
|
|
169
|
-
k--;
|
|
170
|
-
}
|
|
171
|
-
if (bs % 2 === 0) {
|
|
172
|
-
lastPos = i;
|
|
173
|
-
break;
|
|
174
|
-
}
|
|
208
|
+
// check escaped
|
|
209
|
+
let bs = 0, k = i - 1;
|
|
210
|
+
while (k >= 0 && v[k] === '\\') { bs++; k--; }
|
|
211
|
+
if (bs % 2 === 0) { lastPos = i; break; }
|
|
175
212
|
}
|
|
176
213
|
}
|
|
177
|
-
const inner
|
|
178
|
-
return JSON.stringify(inner); //
|
|
214
|
+
const inner = lastPos > 0 ? v.slice(1, lastPos) : v.slice(1);
|
|
215
|
+
return JSON.stringify(inner); // Use JSON.stringify to generate valid JSON string (automatically escape internal quotes, etc.)
|
|
179
216
|
}
|
|
180
217
|
|
|
181
|
-
// If
|
|
218
|
+
// If it's an object or array literal (not wrapped in quotes) -> recursively treat as new outermost layer
|
|
182
219
|
if (v.startsWith('{')) {
|
|
183
220
|
return processTopObject(v, depth, MAX_DEPTH);
|
|
184
221
|
}
|
|
@@ -186,25 +223,21 @@ function repairPossiblyQuotedValue(rawVal: string, depth: number, MAX_DEPTH: num
|
|
|
186
223
|
return processTopArray(v, depth, MAX_DEPTH);
|
|
187
224
|
}
|
|
188
225
|
|
|
189
|
-
//
|
|
226
|
+
// Others (numbers, boolean, null, or JS expressions): return as-is
|
|
190
227
|
return v;
|
|
191
228
|
}
|
|
192
229
|
|
|
193
|
-
/* ---------
|
|
230
|
+
/* --------- Utilities: Split by top-level commas, find top-level colon, extract key --------- */
|
|
194
231
|
|
|
195
|
-
// Split
|
|
232
|
+
// Split by top-level commas (ignore strings, sub-objects, sub-arrays, commas inside parentheses)
|
|
196
233
|
function splitTopLevel(str: string): string[] {
|
|
197
234
|
const parts: string[] = [];
|
|
198
|
-
let buf
|
|
199
|
-
let depthCurly
|
|
200
|
-
let
|
|
201
|
-
let depthParen: number = 0;
|
|
202
|
-
let inSingle: boolean = false;
|
|
203
|
-
let inDouble: boolean = false;
|
|
204
|
-
let esc: boolean = false;
|
|
235
|
+
let buf = '';
|
|
236
|
+
let depthCurly = 0, depthSquare = 0, depthParen = 0;
|
|
237
|
+
let inSingle = false, inDouble = false, esc = false;
|
|
205
238
|
|
|
206
|
-
for (let i
|
|
207
|
-
const ch
|
|
239
|
+
for (let i = 0; i < str.length; i++) {
|
|
240
|
+
const ch = str[i];
|
|
208
241
|
|
|
209
242
|
if (esc) {
|
|
210
243
|
buf += ch;
|
|
@@ -217,48 +250,16 @@ function splitTopLevel(str: string): string[] {
|
|
|
217
250
|
continue;
|
|
218
251
|
}
|
|
219
252
|
|
|
220
|
-
if (ch === "'" && !inDouble) {
|
|
221
|
-
|
|
222
|
-
buf += ch;
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
if (ch === '"' && !inSingle) {
|
|
226
|
-
inDouble = !inDouble;
|
|
227
|
-
buf += ch;
|
|
228
|
-
continue;
|
|
229
|
-
}
|
|
253
|
+
if (ch === "'" && !inDouble) { inSingle = !inSingle; buf += ch; continue; }
|
|
254
|
+
if (ch === '"' && !inSingle) { inDouble = !inDouble; buf += ch; continue; }
|
|
230
255
|
|
|
231
256
|
if (!inSingle && !inDouble) {
|
|
232
|
-
if (ch === '{') {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
if (ch === '
|
|
238
|
-
depthCurly--;
|
|
239
|
-
buf += ch;
|
|
240
|
-
continue;
|
|
241
|
-
}
|
|
242
|
-
if (ch === '[') {
|
|
243
|
-
depthSquare++;
|
|
244
|
-
buf += ch;
|
|
245
|
-
continue;
|
|
246
|
-
}
|
|
247
|
-
if (ch === ']') {
|
|
248
|
-
depthSquare--;
|
|
249
|
-
buf += ch;
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
if (ch === '(') {
|
|
253
|
-
depthParen++;
|
|
254
|
-
buf += ch;
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
if (ch === ')') {
|
|
258
|
-
depthParen--;
|
|
259
|
-
buf += ch;
|
|
260
|
-
continue;
|
|
261
|
-
}
|
|
257
|
+
if (ch === '{') { depthCurly++; buf += ch; continue; }
|
|
258
|
+
if (ch === '}') { depthCurly--; buf += ch; continue; }
|
|
259
|
+
if (ch === '[') { depthSquare++; buf += ch; continue; }
|
|
260
|
+
if (ch === ']') { depthSquare--; buf += ch; continue; }
|
|
261
|
+
if (ch === '(') { depthParen++; buf += ch; continue; }
|
|
262
|
+
if (ch === ')') { depthParen--; buf += ch; continue; }
|
|
262
263
|
|
|
263
264
|
if (ch === ',' && depthCurly === 0 && depthSquare === 0 && depthParen === 0) {
|
|
264
265
|
parts.push(buf);
|
|
@@ -269,63 +270,34 @@ function splitTopLevel(str: string): string[] {
|
|
|
269
270
|
|
|
270
271
|
buf += ch;
|
|
271
272
|
}
|
|
273
|
+
|
|
274
|
+
// Check for unclosed brackets or quotes
|
|
275
|
+
if (depthCurly !== 0 || depthSquare !== 0 || depthParen !== 0 || inSingle || inDouble) {
|
|
276
|
+
throw new Error('Invalid JSON: unclosed brackets or quotes');
|
|
277
|
+
}
|
|
278
|
+
|
|
272
279
|
if (buf.trim() !== '') parts.push(buf);
|
|
273
280
|
return parts;
|
|
274
281
|
}
|
|
275
282
|
|
|
276
|
-
// Find the first top-level colon (
|
|
283
|
+
// Find the first "top-level" colon index (ignore inside strings & sub-levels)
|
|
277
284
|
function findTopLevelColon(str: string): number {
|
|
278
|
-
let inSingle
|
|
279
|
-
let
|
|
280
|
-
let
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const ch: string = str[i];
|
|
287
|
-
if (esc) {
|
|
288
|
-
esc = false;
|
|
289
|
-
continue;
|
|
290
|
-
}
|
|
291
|
-
if (ch === '\\') {
|
|
292
|
-
esc = true;
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
if (ch === "'" && !inDouble) {
|
|
296
|
-
inSingle = !inSingle;
|
|
297
|
-
continue;
|
|
298
|
-
}
|
|
299
|
-
if (ch === '"' && !inSingle) {
|
|
300
|
-
inDouble = !inDouble;
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
285
|
+
let inSingle = false, inDouble = false, esc = false;
|
|
286
|
+
let depthCurly = 0, depthSquare = 0, depthParen = 0;
|
|
287
|
+
for (let i = 0; i < str.length; i++) {
|
|
288
|
+
const ch = str[i];
|
|
289
|
+
if (esc) { esc = false; continue; }
|
|
290
|
+
if (ch === '\\') { esc = true; continue; }
|
|
291
|
+
if (ch === "'" && !inDouble) { inSingle = !inSingle; continue; }
|
|
292
|
+
if (ch === '"' && !inSingle) { inDouble = !inDouble; continue; }
|
|
303
293
|
|
|
304
294
|
if (!inSingle && !inDouble) {
|
|
305
|
-
if (ch === '{') {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
if (ch === '
|
|
310
|
-
|
|
311
|
-
continue;
|
|
312
|
-
}
|
|
313
|
-
if (ch === '[') {
|
|
314
|
-
depthSquare++;
|
|
315
|
-
continue;
|
|
316
|
-
}
|
|
317
|
-
if (ch === ']') {
|
|
318
|
-
depthSquare--;
|
|
319
|
-
continue;
|
|
320
|
-
}
|
|
321
|
-
if (ch === '(') {
|
|
322
|
-
depthParen++;
|
|
323
|
-
continue;
|
|
324
|
-
}
|
|
325
|
-
if (ch === ')') {
|
|
326
|
-
depthParen--;
|
|
327
|
-
continue;
|
|
328
|
-
}
|
|
295
|
+
if (ch === '{') { depthCurly++; continue; }
|
|
296
|
+
if (ch === '}') { depthCurly--; continue; }
|
|
297
|
+
if (ch === '[') { depthSquare++; continue; }
|
|
298
|
+
if (ch === ']') { depthSquare--; continue; }
|
|
299
|
+
if (ch === '(') { depthParen++; continue; }
|
|
300
|
+
if (ch === ')') { depthParen--; continue; }
|
|
329
301
|
|
|
330
302
|
if (ch === ':' && depthCurly === 0 && depthSquare === 0 && depthParen === 0) {
|
|
331
303
|
return i;
|
|
@@ -335,16 +307,17 @@ function findTopLevelColon(str: string): number {
|
|
|
335
307
|
return -1;
|
|
336
308
|
}
|
|
337
309
|
|
|
338
|
-
// Extract key content (supports "key", 'key', key)
|
|
310
|
+
// Extract key content (supports "key", 'key', key), returns pure key string
|
|
339
311
|
function extractKeyContent(rawKey: string): string {
|
|
340
|
-
const r
|
|
312
|
+
const r = rawKey.trim();
|
|
341
313
|
if ((r.startsWith('"') && r.endsWith('"')) || (r.startsWith("'") && r.endsWith("'"))) {
|
|
342
|
-
const inner
|
|
314
|
+
const inner = r.slice(1, -1).replace(/\\"/g, '"').replace(/\\'/g, "'");
|
|
343
315
|
return inner;
|
|
344
316
|
}
|
|
345
317
|
return r;
|
|
346
318
|
}
|
|
347
319
|
|
|
320
|
+
|
|
348
321
|
/**
|
|
349
322
|
* Determine whether it is in JSON format
|
|
350
323
|
* @private
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "UIUX Lab",
|
|
3
3
|
"email": "uiuxlab@gmail.com",
|
|
4
4
|
"name": "funda-ui",
|
|
5
|
-
"version": "4.7.
|
|
5
|
+
"version": "4.7.608",
|
|
6
6
|
"description": "React components using pure Bootstrap 5+ which does not contain any external style and script libraries.",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|