@etsoo/shared 1.2.79 → 1.2.81
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/.github/workflows/main.yml +5 -3
- package/README.md +1 -0
- package/__tests__/Utils.ts +24 -0
- package/lib/cjs/Utils.d.ts +17 -0
- package/lib/cjs/Utils.js +94 -1
- package/lib/cjs/storage/IStorage.d.ts +1 -1
- package/lib/cjs/storage/WindowStorage.d.ts +1 -1
- package/lib/mjs/Utils.d.ts +17 -0
- package/lib/mjs/Utils.js +94 -1
- package/lib/mjs/storage/IStorage.d.ts +1 -1
- package/lib/mjs/storage/WindowStorage.d.ts +1 -1
- package/package.json +5 -5
- package/src/Utils.ts +105 -3
- package/src/storage/IStorage.ts +1 -1
- package/src/storage/WindowStorage.ts +1 -1
|
@@ -11,6 +11,10 @@ on:
|
|
|
11
11
|
# release:
|
|
12
12
|
# types: [created]
|
|
13
13
|
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write # Required for OIDC
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
14
18
|
jobs:
|
|
15
19
|
# Publish to NPM
|
|
16
20
|
publish-npm:
|
|
@@ -44,6 +48,4 @@ jobs:
|
|
|
44
48
|
|
|
45
49
|
# Publish to npm
|
|
46
50
|
# For scoped package, make it public for free service
|
|
47
|
-
- run: npm publish
|
|
48
|
-
env:
|
|
49
|
-
NODE_AUTH_TOKEN: ${{ secrets.ETSOONpmToken }}
|
|
51
|
+
- run: npm publish
|
package/README.md
CHANGED
|
@@ -324,6 +324,7 @@ String and other related utilities
|
|
|
324
324
|
| objectKeys | Get two object's unqiue properties |
|
|
325
325
|
| objectUpdated | Get the new object's updated fields contrast to the previous object |
|
|
326
326
|
| parseJsonArray | Try to parse JSON input to array |
|
|
327
|
+
| parseName | Parse name data |
|
|
327
328
|
| parsePath | Parse path similar with node.js path.parse |
|
|
328
329
|
| parseString | Parse string (JSON) to specific type |
|
|
329
330
|
| removeEmptyValues | Remove empty values (null, undefined, '') from the input object |
|
package/__tests__/Utils.ts
CHANGED
|
@@ -328,6 +328,16 @@ test("Tests for mergeClasses", () => {
|
|
|
328
328
|
expect(Utils.mergeClasses("a", "", "b ", undefined, "c")).toBe("a b c");
|
|
329
329
|
});
|
|
330
330
|
|
|
331
|
+
test("Tests for formatName", () => {
|
|
332
|
+
expect(Utils.formatName("青岛亿速思维网络科技有限公司", 6)).toBe(
|
|
333
|
+
"青岛亿速思维"
|
|
334
|
+
);
|
|
335
|
+
expect(Utils.formatName("亿速思维(中国)网络科技有限公司", 6)).toBe(
|
|
336
|
+
"亿速思维(中国)"
|
|
337
|
+
);
|
|
338
|
+
expect(Utils.formatName("John Smith", 6)).toBe("John Smith");
|
|
339
|
+
});
|
|
340
|
+
|
|
331
341
|
test("Tests for getNestedValue", () => {
|
|
332
342
|
const obj = { jsonData: { photoSize: [200, 100], supportResizing: true } };
|
|
333
343
|
expect(Utils.getNestedValue(obj, "jsonData.supportResizing")).toBeTruthy();
|
|
@@ -356,6 +366,20 @@ test("Tests for getResult", () => {
|
|
|
356
366
|
expect(valueResult).toBe(5);
|
|
357
367
|
});
|
|
358
368
|
|
|
369
|
+
test("Tests for parseName", () => {
|
|
370
|
+
const nd = Utils.parseName("王小明");
|
|
371
|
+
expect(nd.familyName).toBe("王");
|
|
372
|
+
expect(nd.givenName).toBe("小明");
|
|
373
|
+
|
|
374
|
+
const nd2 = Utils.parseName("John Smith");
|
|
375
|
+
expect(nd2.familyName).toBe("Smith");
|
|
376
|
+
expect(nd2.givenName).toBe("John");
|
|
377
|
+
|
|
378
|
+
const nd3 = Utils.parseName("单 名");
|
|
379
|
+
expect(nd3.familyName).toBe("单");
|
|
380
|
+
expect(nd3.givenName).toBe("名");
|
|
381
|
+
});
|
|
382
|
+
|
|
359
383
|
test("Tests for parsePath, file only", () => {
|
|
360
384
|
const result = Utils.parsePath("a.jpg");
|
|
361
385
|
expect(result.root).toBe("");
|
package/lib/cjs/Utils.d.ts
CHANGED
|
@@ -132,6 +132,14 @@ export declare namespace Utils {
|
|
|
132
132
|
export function excludeAsync<T extends {
|
|
133
133
|
[P in D]: IdType;
|
|
134
134
|
}, D extends string = "id">(items: Promise<T[] | undefined>, field: D, ...excludedValues: T[D][]): Promise<T[] | undefined>;
|
|
135
|
+
/**
|
|
136
|
+
* Format name
|
|
137
|
+
* @param name Input name
|
|
138
|
+
* @param maxChars Max chars
|
|
139
|
+
* @param maxParts Max parts (optional)
|
|
140
|
+
* @returns Formatted name
|
|
141
|
+
*/
|
|
142
|
+
export function formatName(name: string, maxChars: number, maxParts?: number): string;
|
|
135
143
|
/**
|
|
136
144
|
* Format inital character to lower case or upper case
|
|
137
145
|
* @param input Input string
|
|
@@ -306,6 +314,15 @@ export declare namespace Utils {
|
|
|
306
314
|
* @param keepNull Keep null value or not
|
|
307
315
|
*/
|
|
308
316
|
export function setNestedValue(data: object, name: string, value: unknown, keepNull?: boolean): void;
|
|
317
|
+
/**
|
|
318
|
+
* Parse name
|
|
319
|
+
* @param name Name
|
|
320
|
+
* @returns Result
|
|
321
|
+
*/
|
|
322
|
+
export function parseName(name: string): {
|
|
323
|
+
familyName: string | undefined;
|
|
324
|
+
givenName: string | undefined;
|
|
325
|
+
};
|
|
309
326
|
/**
|
|
310
327
|
* Parse path similar with node.js path.parse
|
|
311
328
|
* @param path Input path
|
package/lib/cjs/Utils.js
CHANGED
|
@@ -207,6 +207,63 @@ var Utils;
|
|
|
207
207
|
return exclude(result, field, ...excludedValues);
|
|
208
208
|
}
|
|
209
209
|
Utils.excludeAsync = excludeAsync;
|
|
210
|
+
/**
|
|
211
|
+
* Format name
|
|
212
|
+
* @param name Input name
|
|
213
|
+
* @param maxChars Max chars
|
|
214
|
+
* @param maxParts Max parts (optional)
|
|
215
|
+
* @returns Formatted name
|
|
216
|
+
*/
|
|
217
|
+
function formatName(name, maxChars, maxParts) {
|
|
218
|
+
name = name.trim();
|
|
219
|
+
const parts = name.split(/\s+/);
|
|
220
|
+
const max = maxParts ?? Math.floor(maxChars / 3);
|
|
221
|
+
const effectiveMax = max < 2 ? 2 : max;
|
|
222
|
+
if (parts.length >= effectiveMax) {
|
|
223
|
+
return parts.slice(0, effectiveMax).join(" ");
|
|
224
|
+
}
|
|
225
|
+
else if (name.length > maxChars) {
|
|
226
|
+
let endIndex = maxChars;
|
|
227
|
+
const brackets = {
|
|
228
|
+
"(": ")",
|
|
229
|
+
"(": ")",
|
|
230
|
+
"[": "]"
|
|
231
|
+
};
|
|
232
|
+
// Count unmatched brackets for each type
|
|
233
|
+
for (const [start, end] of Object.entries(brackets)) {
|
|
234
|
+
let count = 0;
|
|
235
|
+
// Count opening and closing brackets in the substring
|
|
236
|
+
for (let i = 0; i < maxChars; i++) {
|
|
237
|
+
if (name[i] === start)
|
|
238
|
+
count++;
|
|
239
|
+
else if (name[i] === end)
|
|
240
|
+
count--;
|
|
241
|
+
}
|
|
242
|
+
if (count > 0) {
|
|
243
|
+
// Find matching end brackets
|
|
244
|
+
for (let i = maxChars; i < name.length && count > 0; i++) {
|
|
245
|
+
if (name[i] === start) {
|
|
246
|
+
count++;
|
|
247
|
+
}
|
|
248
|
+
else if (name[i] === end) {
|
|
249
|
+
count--;
|
|
250
|
+
if (count === 0) {
|
|
251
|
+
endIndex = i + 1;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (count === 0) {
|
|
256
|
+
return name.substring(0, endIndex);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return name.substring(0, endIndex);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
return name;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
Utils.formatName = formatName;
|
|
210
267
|
/**
|
|
211
268
|
* Format inital character to lower case or upper case
|
|
212
269
|
* @param input Input string
|
|
@@ -578,7 +635,7 @@ var Utils;
|
|
|
578
635
|
Utils.setLabels = (source, labels, reference) => {
|
|
579
636
|
Object.keys(source).forEach((key) => {
|
|
580
637
|
// Reference key
|
|
581
|
-
const labelKey = reference == null ? key : reference[key] ?? key;
|
|
638
|
+
const labelKey = reference == null ? key : (reference[key] ?? key);
|
|
582
639
|
// Label
|
|
583
640
|
const label = labels[labelKey];
|
|
584
641
|
if (label != null) {
|
|
@@ -647,6 +704,42 @@ var Utils;
|
|
|
647
704
|
}
|
|
648
705
|
}
|
|
649
706
|
Utils.setNestedValue = setNestedValue;
|
|
707
|
+
/**
|
|
708
|
+
* Parse name
|
|
709
|
+
* @param name Name
|
|
710
|
+
* @returns Result
|
|
711
|
+
*/
|
|
712
|
+
function parseName(name) {
|
|
713
|
+
// Trim
|
|
714
|
+
name = name.trim();
|
|
715
|
+
let familyName;
|
|
716
|
+
let givenName;
|
|
717
|
+
if (name.containChinese() ||
|
|
718
|
+
name.containJapanese() ||
|
|
719
|
+
name.containKorean()) {
|
|
720
|
+
// CJK characters
|
|
721
|
+
if (name.length >= 2) {
|
|
722
|
+
familyName = name[0];
|
|
723
|
+
givenName = name.substring(1).trim();
|
|
724
|
+
}
|
|
725
|
+
else {
|
|
726
|
+
familyName = name;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
else {
|
|
730
|
+
const parts = name.split(/\s+/);
|
|
731
|
+
const len = parts.length;
|
|
732
|
+
if (len >= 2) {
|
|
733
|
+
familyName = parts[len - 1];
|
|
734
|
+
givenName = parts[0];
|
|
735
|
+
}
|
|
736
|
+
else {
|
|
737
|
+
givenName = name;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
return { familyName, givenName };
|
|
741
|
+
}
|
|
742
|
+
Utils.parseName = parseName;
|
|
650
743
|
/**
|
|
651
744
|
* Parse path similar with node.js path.parse
|
|
652
745
|
* @param path Input path
|
package/lib/mjs/Utils.d.ts
CHANGED
|
@@ -132,6 +132,14 @@ export declare namespace Utils {
|
|
|
132
132
|
export function excludeAsync<T extends {
|
|
133
133
|
[P in D]: IdType;
|
|
134
134
|
}, D extends string = "id">(items: Promise<T[] | undefined>, field: D, ...excludedValues: T[D][]): Promise<T[] | undefined>;
|
|
135
|
+
/**
|
|
136
|
+
* Format name
|
|
137
|
+
* @param name Input name
|
|
138
|
+
* @param maxChars Max chars
|
|
139
|
+
* @param maxParts Max parts (optional)
|
|
140
|
+
* @returns Formatted name
|
|
141
|
+
*/
|
|
142
|
+
export function formatName(name: string, maxChars: number, maxParts?: number): string;
|
|
135
143
|
/**
|
|
136
144
|
* Format inital character to lower case or upper case
|
|
137
145
|
* @param input Input string
|
|
@@ -306,6 +314,15 @@ export declare namespace Utils {
|
|
|
306
314
|
* @param keepNull Keep null value or not
|
|
307
315
|
*/
|
|
308
316
|
export function setNestedValue(data: object, name: string, value: unknown, keepNull?: boolean): void;
|
|
317
|
+
/**
|
|
318
|
+
* Parse name
|
|
319
|
+
* @param name Name
|
|
320
|
+
* @returns Result
|
|
321
|
+
*/
|
|
322
|
+
export function parseName(name: string): {
|
|
323
|
+
familyName: string | undefined;
|
|
324
|
+
givenName: string | undefined;
|
|
325
|
+
};
|
|
309
326
|
/**
|
|
310
327
|
* Parse path similar with node.js path.parse
|
|
311
328
|
* @param path Input path
|
package/lib/mjs/Utils.js
CHANGED
|
@@ -204,6 +204,63 @@ export var Utils;
|
|
|
204
204
|
return exclude(result, field, ...excludedValues);
|
|
205
205
|
}
|
|
206
206
|
Utils.excludeAsync = excludeAsync;
|
|
207
|
+
/**
|
|
208
|
+
* Format name
|
|
209
|
+
* @param name Input name
|
|
210
|
+
* @param maxChars Max chars
|
|
211
|
+
* @param maxParts Max parts (optional)
|
|
212
|
+
* @returns Formatted name
|
|
213
|
+
*/
|
|
214
|
+
function formatName(name, maxChars, maxParts) {
|
|
215
|
+
name = name.trim();
|
|
216
|
+
const parts = name.split(/\s+/);
|
|
217
|
+
const max = maxParts ?? Math.floor(maxChars / 3);
|
|
218
|
+
const effectiveMax = max < 2 ? 2 : max;
|
|
219
|
+
if (parts.length >= effectiveMax) {
|
|
220
|
+
return parts.slice(0, effectiveMax).join(" ");
|
|
221
|
+
}
|
|
222
|
+
else if (name.length > maxChars) {
|
|
223
|
+
let endIndex = maxChars;
|
|
224
|
+
const brackets = {
|
|
225
|
+
"(": ")",
|
|
226
|
+
"(": ")",
|
|
227
|
+
"[": "]"
|
|
228
|
+
};
|
|
229
|
+
// Count unmatched brackets for each type
|
|
230
|
+
for (const [start, end] of Object.entries(brackets)) {
|
|
231
|
+
let count = 0;
|
|
232
|
+
// Count opening and closing brackets in the substring
|
|
233
|
+
for (let i = 0; i < maxChars; i++) {
|
|
234
|
+
if (name[i] === start)
|
|
235
|
+
count++;
|
|
236
|
+
else if (name[i] === end)
|
|
237
|
+
count--;
|
|
238
|
+
}
|
|
239
|
+
if (count > 0) {
|
|
240
|
+
// Find matching end brackets
|
|
241
|
+
for (let i = maxChars; i < name.length && count > 0; i++) {
|
|
242
|
+
if (name[i] === start) {
|
|
243
|
+
count++;
|
|
244
|
+
}
|
|
245
|
+
else if (name[i] === end) {
|
|
246
|
+
count--;
|
|
247
|
+
if (count === 0) {
|
|
248
|
+
endIndex = i + 1;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (count === 0) {
|
|
253
|
+
return name.substring(0, endIndex);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return name.substring(0, endIndex);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
return name;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
Utils.formatName = formatName;
|
|
207
264
|
/**
|
|
208
265
|
* Format inital character to lower case or upper case
|
|
209
266
|
* @param input Input string
|
|
@@ -575,7 +632,7 @@ export var Utils;
|
|
|
575
632
|
Utils.setLabels = (source, labels, reference) => {
|
|
576
633
|
Object.keys(source).forEach((key) => {
|
|
577
634
|
// Reference key
|
|
578
|
-
const labelKey = reference == null ? key : reference[key] ?? key;
|
|
635
|
+
const labelKey = reference == null ? key : (reference[key] ?? key);
|
|
579
636
|
// Label
|
|
580
637
|
const label = labels[labelKey];
|
|
581
638
|
if (label != null) {
|
|
@@ -644,6 +701,42 @@ export var Utils;
|
|
|
644
701
|
}
|
|
645
702
|
}
|
|
646
703
|
Utils.setNestedValue = setNestedValue;
|
|
704
|
+
/**
|
|
705
|
+
* Parse name
|
|
706
|
+
* @param name Name
|
|
707
|
+
* @returns Result
|
|
708
|
+
*/
|
|
709
|
+
function parseName(name) {
|
|
710
|
+
// Trim
|
|
711
|
+
name = name.trim();
|
|
712
|
+
let familyName;
|
|
713
|
+
let givenName;
|
|
714
|
+
if (name.containChinese() ||
|
|
715
|
+
name.containJapanese() ||
|
|
716
|
+
name.containKorean()) {
|
|
717
|
+
// CJK characters
|
|
718
|
+
if (name.length >= 2) {
|
|
719
|
+
familyName = name[0];
|
|
720
|
+
givenName = name.substring(1).trim();
|
|
721
|
+
}
|
|
722
|
+
else {
|
|
723
|
+
familyName = name;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
const parts = name.split(/\s+/);
|
|
728
|
+
const len = parts.length;
|
|
729
|
+
if (len >= 2) {
|
|
730
|
+
familyName = parts[len - 1];
|
|
731
|
+
givenName = parts[0];
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
givenName = name;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
return { familyName, givenName };
|
|
738
|
+
}
|
|
739
|
+
Utils.parseName = parseName;
|
|
647
740
|
/**
|
|
648
741
|
* Parse path similar with node.js path.parse
|
|
649
742
|
* @param path Input path
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/shared",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.81",
|
|
4
4
|
"description": "TypeScript shared utilities and functions",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/mjs/index.js",
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://github.com/ETSOO/Shared#readme",
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@types/node": "^
|
|
40
|
-
"@vitejs/plugin-react": "^
|
|
41
|
-
"jsdom": "^
|
|
39
|
+
"@types/node": "^25.5.0",
|
|
40
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
41
|
+
"jsdom": "^29.0.1",
|
|
42
42
|
"typescript": "^5.9.3",
|
|
43
|
-
"vitest": "^4.
|
|
43
|
+
"vitest": "^4.1.2"
|
|
44
44
|
}
|
|
45
45
|
}
|
package/src/Utils.ts
CHANGED
|
@@ -355,6 +355,70 @@ export namespace Utils {
|
|
|
355
355
|
return exclude(result, field, ...excludedValues);
|
|
356
356
|
}
|
|
357
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Format name
|
|
360
|
+
* @param name Input name
|
|
361
|
+
* @param maxChars Max chars
|
|
362
|
+
* @param maxParts Max parts (optional)
|
|
363
|
+
* @returns Formatted name
|
|
364
|
+
*/
|
|
365
|
+
export function formatName(
|
|
366
|
+
name: string,
|
|
367
|
+
maxChars: number,
|
|
368
|
+
maxParts?: number
|
|
369
|
+
): string {
|
|
370
|
+
name = name.trim();
|
|
371
|
+
|
|
372
|
+
const parts = name.split(/\s+/);
|
|
373
|
+
|
|
374
|
+
const max = maxParts ?? Math.floor(maxChars / 3);
|
|
375
|
+
const effectiveMax = max < 2 ? 2 : max;
|
|
376
|
+
|
|
377
|
+
if (parts.length >= effectiveMax) {
|
|
378
|
+
return parts.slice(0, effectiveMax).join(" ");
|
|
379
|
+
} else if (name.length > maxChars) {
|
|
380
|
+
let endIndex = maxChars;
|
|
381
|
+
const brackets: Record<string, string> = {
|
|
382
|
+
"(": ")",
|
|
383
|
+
"(": ")",
|
|
384
|
+
"[": "]"
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// Count unmatched brackets for each type
|
|
388
|
+
for (const [start, end] of Object.entries(brackets)) {
|
|
389
|
+
let count = 0;
|
|
390
|
+
|
|
391
|
+
// Count opening and closing brackets in the substring
|
|
392
|
+
for (let i = 0; i < maxChars; i++) {
|
|
393
|
+
if (name[i] === start) count++;
|
|
394
|
+
else if (name[i] === end) count--;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (count > 0) {
|
|
398
|
+
// Find matching end brackets
|
|
399
|
+
for (let i = maxChars; i < name.length && count > 0; i++) {
|
|
400
|
+
if (name[i] === start) {
|
|
401
|
+
count++;
|
|
402
|
+
} else if (name[i] === end) {
|
|
403
|
+
count--;
|
|
404
|
+
if (count === 0) {
|
|
405
|
+
endIndex = i + 1;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (count === 0) {
|
|
411
|
+
return name.substring(0, endIndex);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return name.substring(0, endIndex);
|
|
417
|
+
} else {
|
|
418
|
+
return name;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
358
422
|
/**
|
|
359
423
|
* Format inital character to lower case or upper case
|
|
360
424
|
* @param input Input string
|
|
@@ -823,7 +887,7 @@ export namespace Utils {
|
|
|
823
887
|
) => {
|
|
824
888
|
Object.keys(source).forEach((key) => {
|
|
825
889
|
// Reference key
|
|
826
|
-
const labelKey = reference == null ? key : reference[key] ?? key;
|
|
890
|
+
const labelKey = reference == null ? key : (reference[key] ?? key);
|
|
827
891
|
|
|
828
892
|
// Label
|
|
829
893
|
const label = labels[labelKey];
|
|
@@ -899,6 +963,44 @@ export namespace Utils {
|
|
|
899
963
|
}
|
|
900
964
|
}
|
|
901
965
|
|
|
966
|
+
/**
|
|
967
|
+
* Parse name
|
|
968
|
+
* @param name Name
|
|
969
|
+
* @returns Result
|
|
970
|
+
*/
|
|
971
|
+
export function parseName(name: string) {
|
|
972
|
+
// Trim
|
|
973
|
+
name = name.trim();
|
|
974
|
+
|
|
975
|
+
let familyName: string | undefined;
|
|
976
|
+
let givenName: string | undefined;
|
|
977
|
+
|
|
978
|
+
if (
|
|
979
|
+
name.containChinese() ||
|
|
980
|
+
name.containJapanese() ||
|
|
981
|
+
name.containKorean()
|
|
982
|
+
) {
|
|
983
|
+
// CJK characters
|
|
984
|
+
if (name.length >= 2) {
|
|
985
|
+
familyName = name[0];
|
|
986
|
+
givenName = name.substring(1).trim();
|
|
987
|
+
} else {
|
|
988
|
+
familyName = name;
|
|
989
|
+
}
|
|
990
|
+
} else {
|
|
991
|
+
const parts = name.split(/\s+/);
|
|
992
|
+
const len = parts.length;
|
|
993
|
+
if (len >= 2) {
|
|
994
|
+
familyName = parts[len - 1];
|
|
995
|
+
givenName = parts[0];
|
|
996
|
+
} else {
|
|
997
|
+
givenName = name;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
return { familyName, givenName };
|
|
1002
|
+
}
|
|
1003
|
+
|
|
902
1004
|
/**
|
|
903
1005
|
* Parse path similar with node.js path.parse
|
|
904
1006
|
* @param path Input path
|
|
@@ -925,8 +1027,8 @@ export namespace Utils {
|
|
|
925
1027
|
index1 === -1
|
|
926
1028
|
? index2
|
|
927
1029
|
: index2 === -1
|
|
928
|
-
|
|
929
|
-
|
|
1030
|
+
? index1
|
|
1031
|
+
: Math.min(index1, index2);
|
|
930
1032
|
root = path.substring(0, index + 1);
|
|
931
1033
|
dir = path.substring(0, lastIndex);
|
|
932
1034
|
if (dir === "") dir = root;
|
package/src/storage/IStorage.ts
CHANGED
|
@@ -141,7 +141,7 @@ export class WindowStorage implements IStorage {
|
|
|
141
141
|
* @param key Key name
|
|
142
142
|
* @param data Data, null for removal
|
|
143
143
|
*/
|
|
144
|
-
setPersistedData(key: string, data:
|
|
144
|
+
setPersistedData<T>(key: string, data: T) {
|
|
145
145
|
StorageUtils.setLocalData(key, data);
|
|
146
146
|
}
|
|
147
147
|
}
|