@digitalwalletcorp/utils 0.10.0 → 0.12.0
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/README.md +1 -0
- package/lib/date-util-BNe2E-tA.js +140 -0
- package/lib/date-util-BNe2E-tA.js.map +1 -0
- package/lib/date-util-CZmiQEYH.cjs +2 -0
- package/lib/date-util-CZmiQEYH.cjs.map +1 -0
- package/lib/date-util.cjs +1 -1
- package/lib/date-util.d.cts +8 -15
- package/lib/date-util.d.ts +8 -15
- package/lib/date-util.js +15 -16
- package/lib/html-util-BctKzfnH.js +60 -0
- package/lib/html-util-BctKzfnH.js.map +1 -0
- package/lib/html-util-ELyFVsxl.cjs +2 -0
- package/lib/html-util-ELyFVsxl.cjs.map +1 -0
- package/lib/html-util.cjs +1 -1
- package/lib/html-util.d.cts +5 -4
- package/lib/html-util.d.ts +5 -4
- package/lib/html-util.js +2 -2
- package/lib/index.cjs +1 -1
- package/lib/index.d.cts +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +15 -13
- package/lib/index.js.map +1 -1
- package/lib/{json-util-5mq7fsX_.cjs → json-util-CKnsxu1e.cjs} +3 -3
- package/lib/json-util-CKnsxu1e.cjs.map +1 -0
- package/lib/{json-util-CF-O1b7m.js → json-util-C_Pm1BpJ.js} +6 -5
- package/lib/json-util-C_Pm1BpJ.js.map +1 -0
- package/lib/json-util.cjs +1 -1
- package/lib/json-util.d.cts +10 -1
- package/lib/json-util.d.ts +10 -1
- package/lib/json-util.js +1 -1
- package/lib/{object-util-Cc1SmN-8.cjs → object-util-BHg61ifG.cjs} +2 -2
- package/lib/{object-util-Cc1SmN-8.cjs.map → object-util-BHg61ifG.cjs.map} +1 -1
- package/lib/{object-util-BGqczDbJ.js → object-util-wOMJtGK3.js} +2 -2
- package/lib/{object-util-BGqczDbJ.js.map → object-util-wOMJtGK3.js.map} +1 -1
- package/lib/object-util.cjs +1 -1
- package/lib/object-util.js +2 -2
- package/lib/zoned-date-time.cjs +2 -0
- package/lib/zoned-date-time.cjs.map +1 -0
- package/lib/zoned-date-time.d.cts +203 -0
- package/lib/zoned-date-time.d.ts +203 -0
- package/lib/zoned-date-time.js +289 -0
- package/lib/zoned-date-time.js.map +1 -0
- package/package.json +1 -1
- package/src/date-util.ts +29 -103
- package/src/html-util.ts +22 -12
- package/src/index.ts +1 -0
- package/src/json-util.ts +8 -5
- package/src/zoned-date-time.ts +395 -0
- package/lib/date-util-DrfUsv9b.js +0 -181
- package/lib/date-util-DrfUsv9b.js.map +0 -1
- package/lib/date-util-b1Lw7Nyu.cjs +0 -2
- package/lib/date-util-b1Lw7Nyu.cjs.map +0 -1
- package/lib/html-util-CcRJtzod.js +0 -56
- package/lib/html-util-CcRJtzod.js.map +0 -1
- package/lib/html-util-ClGIpzW1.cjs +0 -2
- package/lib/html-util-ClGIpzW1.cjs.map +0 -1
- package/lib/json-util-5mq7fsX_.cjs.map +0 -1
- package/lib/json-util-CF-O1b7m.js.map +0 -1
package/src/date-util.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { DateTimeUnit } from 'luxon';
|
|
1
|
+
import { ZonedDateTime } from './zoned-date-time';
|
|
3
2
|
|
|
4
|
-
/**
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* 日時として解釈する値。string はISO形式または inputFormat の書式、number は epoch ミリ秒
|
|
5
|
+
* ZonedDateTime は inputTimezone を省略した場合、その ZonedDateTime のタイムゾーンで扱う
|
|
6
|
+
*/
|
|
7
|
+
export type DateInput = string | Date | number | ZonedDateTime | null | undefined;
|
|
6
8
|
|
|
7
9
|
/** 日時の切り捨て(startOf / endOf)に使う単位 */
|
|
8
10
|
export type DateUnit = 'year' | 'quarter' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond';
|
|
@@ -37,6 +39,8 @@ export interface ParseDateOptions {
|
|
|
37
39
|
startOf?: DateUnit;
|
|
38
40
|
/** 指定した単位の最後の時点に切り上げる(month なら月末の23:59:59.999) */
|
|
39
41
|
endOf?: DateUnit;
|
|
42
|
+
/** 書式の月名・曜日名を解釈・出力するときのロケール。既定は 'en-US' */
|
|
43
|
+
locale?: string;
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
/**
|
|
@@ -119,65 +123,13 @@ const DEFAULT_TIMEZONE_ABBREVIATIONS: TimezoneAbbreviations = {
|
|
|
119
123
|
'America/Sao_Paulo': { standard: 'BRT' }
|
|
120
124
|
};
|
|
121
125
|
|
|
122
|
-
/**
|
|
123
|
-
* タイムゾーンの指定が不正な場合は、日時の不正とは区別して例外にする
|
|
124
|
-
*/
|
|
125
|
-
const assertZone = (d: DateTime): void => {
|
|
126
|
-
if (!d.isValid && d.invalidReason === 'unsupported zone') {
|
|
127
|
-
throw new RangeError(d.invalidExplanation ?? d.invalidReason);
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const toDateTime = (value: DateInput, options?: ParseDateOptions): DateTime | null => {
|
|
132
|
-
if (value == null || value === '') {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
const zone = options?.inputTimezone ?? DEFAULT_TIMEZONE;
|
|
136
|
-
let d: DateTime | null = null;
|
|
137
|
-
if (value instanceof Date) {
|
|
138
|
-
d = DateTime.fromJSDate(value, { zone: zone });
|
|
139
|
-
} else if (typeof value === 'number') {
|
|
140
|
-
d = Number.isFinite(value) ? DateTime.fromMillis(value, { zone: zone }) : null;
|
|
141
|
-
} else {
|
|
142
|
-
const formats = options?.inputFormat ? [options.inputFormat].flat() : [];
|
|
143
|
-
for (const format of formats) {
|
|
144
|
-
const parsed = DateTime.fromFormat(value, format, { zone: zone });
|
|
145
|
-
assertZone(parsed);
|
|
146
|
-
if (parsed.isValid) {
|
|
147
|
-
d = parsed;
|
|
148
|
-
break;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (d == null) {
|
|
152
|
-
d = DateTime.fromISO(value, { zone: zone });
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
if (d == null) {
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
assertZone(d);
|
|
159
|
-
if (!d.isValid) {
|
|
160
|
-
return null;
|
|
161
|
-
}
|
|
162
|
-
if (options?.duration) {
|
|
163
|
-
d = d.plus(options.duration);
|
|
164
|
-
}
|
|
165
|
-
if (options?.startOf) {
|
|
166
|
-
d = d.startOf(options.startOf);
|
|
167
|
-
}
|
|
168
|
-
if (options?.endOf) {
|
|
169
|
-
d = d.endOf(options.endOf);
|
|
170
|
-
}
|
|
171
|
-
return d;
|
|
172
|
-
};
|
|
173
|
-
|
|
174
126
|
const compare = (date1: DateInput, date2: DateInput, options: ParseDateOptions | undefined, predicate: (v1: number, v2: number) => boolean): boolean => {
|
|
175
|
-
const d1 =
|
|
176
|
-
const d2 =
|
|
127
|
+
const d1 = ZonedDateTime.parse(date1, options);
|
|
128
|
+
const d2 = ZonedDateTime.parse(date2, options);
|
|
177
129
|
if (!d1 || !d2) {
|
|
178
130
|
return false;
|
|
179
131
|
}
|
|
180
|
-
return predicate(d1.
|
|
132
|
+
return predicate(d1.toMillis(), d2.toMillis());
|
|
181
133
|
};
|
|
182
134
|
|
|
183
135
|
/**
|
|
@@ -190,7 +142,7 @@ const compare = (date1: DateInput, date2: DateInput, options: ParseDateOptions |
|
|
|
190
142
|
* @returns {Date | null}
|
|
191
143
|
*/
|
|
192
144
|
export function parseDate(value: DateInput, options?: ParseDateOptions): Date | null {
|
|
193
|
-
return
|
|
145
|
+
return ZonedDateTime.parse(value, options)?.toDate() ?? null;
|
|
194
146
|
}
|
|
195
147
|
|
|
196
148
|
/**
|
|
@@ -206,19 +158,18 @@ export function parseDate(value: DateInput, options?: ParseDateOptions): Date |
|
|
|
206
158
|
export function formatDate(options: FormatDateOptions): string;
|
|
207
159
|
export function formatDate(value: DateInput, options?: FormatDateOptions): string;
|
|
208
160
|
export function formatDate(value: DateInput | FormatDateOptions, options?: FormatDateOptions): string {
|
|
209
|
-
if (typeof value === 'object' && value !== null && !(value instanceof Date)) {
|
|
161
|
+
if (typeof value === 'object' && value !== null && !(value instanceof Date) && !(value instanceof ZonedDateTime)) {
|
|
210
162
|
return formatDate(new Date(), value);
|
|
211
163
|
}
|
|
212
164
|
if (value == null || value === '') {
|
|
213
165
|
return '';
|
|
214
166
|
}
|
|
215
|
-
const d =
|
|
167
|
+
const d = ZonedDateTime.parse(value, options);
|
|
216
168
|
if (!d) {
|
|
217
169
|
return options?.invalidText ?? 'Invalid Date';
|
|
218
170
|
}
|
|
219
171
|
const output = d.setZone(options?.outputTimezone ?? DEFAULT_TIMEZONE);
|
|
220
|
-
|
|
221
|
-
return options?.outputFormat ? output.toFormat(options.outputFormat) : output.toISO() as string;
|
|
172
|
+
return options?.outputFormat ? output.format(options.outputFormat, { locale: options.locale }) : output.toISO();
|
|
222
173
|
}
|
|
223
174
|
|
|
224
175
|
/**
|
|
@@ -229,7 +180,7 @@ export function formatDate(value: DateInput | FormatDateOptions, options?: Forma
|
|
|
229
180
|
* @returns {boolean}
|
|
230
181
|
*/
|
|
231
182
|
export function isValid(value: DateInput, options?: ParseDateOptions): boolean {
|
|
232
|
-
return
|
|
183
|
+
return ZonedDateTime.parse(value, options) != null;
|
|
233
184
|
}
|
|
234
185
|
|
|
235
186
|
/**
|
|
@@ -300,12 +251,12 @@ export function isSameOrAfter(date1: DateInput, date2: DateInput, options?: Pars
|
|
|
300
251
|
* @returns {boolean}
|
|
301
252
|
*/
|
|
302
253
|
export function isPastDate(value: DateInput, options?: ParseDateOptions): boolean {
|
|
303
|
-
const target =
|
|
254
|
+
const target = ZonedDateTime.parse(value, options)?.startOf('day');
|
|
304
255
|
if (!target) {
|
|
305
256
|
return false;
|
|
306
257
|
}
|
|
307
|
-
const today =
|
|
308
|
-
return target.
|
|
258
|
+
const today = ZonedDateTime.now(target.timezone).startOf('day');
|
|
259
|
+
return target.lt(today);
|
|
309
260
|
}
|
|
310
261
|
|
|
311
262
|
/**
|
|
@@ -316,8 +267,8 @@ export function isPastDate(value: DateInput, options?: ParseDateOptions): boolea
|
|
|
316
267
|
* @returns {boolean}
|
|
317
268
|
*/
|
|
318
269
|
export function isPastDateTime(value: DateInput, options?: ParseDateOptions): boolean {
|
|
319
|
-
const target =
|
|
320
|
-
return target != null && target.
|
|
270
|
+
const target = ZonedDateTime.parse(value, options);
|
|
271
|
+
return target != null && target.toMillis() < Date.now();
|
|
321
272
|
}
|
|
322
273
|
|
|
323
274
|
/**
|
|
@@ -332,14 +283,12 @@ export function isPastDateTime(value: DateInput, options?: ParseDateOptions): bo
|
|
|
332
283
|
* @returns {number}
|
|
333
284
|
*/
|
|
334
285
|
export function diff(date1: DateInput, date2: DateInput, unit: TimeUnit, options?: ParseDateOptions): number {
|
|
335
|
-
const d1 =
|
|
336
|
-
const d2 =
|
|
286
|
+
const d1 = ZonedDateTime.parse(date1, options);
|
|
287
|
+
const d2 = ZonedDateTime.parse(date2, options);
|
|
337
288
|
if (!d1 || !d2) {
|
|
338
289
|
return NaN;
|
|
339
290
|
}
|
|
340
|
-
|
|
341
|
-
const dateUnit = unit.slice(0, -1) as DateTimeUnit;
|
|
342
|
-
return d1.startOf(dateUnit).diff(d2.startOf(dateUnit), unit).get(unit);
|
|
291
|
+
return d1.diff(d2, unit);
|
|
343
292
|
}
|
|
344
293
|
|
|
345
294
|
/**
|
|
@@ -349,9 +298,7 @@ export function diff(date1: DateInput, date2: DateInput, unit: TimeUnit, options
|
|
|
349
298
|
* @returns {string}
|
|
350
299
|
*/
|
|
351
300
|
export function currentTimestamp(timezone: string = DEFAULT_TIMEZONE): string {
|
|
352
|
-
|
|
353
|
-
assertZone(d);
|
|
354
|
-
return d.toFormat(TIMESTAMP_FORMAT);
|
|
301
|
+
return ZonedDateTime.now(timezone).format(TIMESTAMP_FORMAT);
|
|
355
302
|
}
|
|
356
303
|
|
|
357
304
|
/**
|
|
@@ -378,22 +325,6 @@ export function convertExcelDateSerialToUnixTimeSerial(excelDateSerial: number,
|
|
|
378
325
|
return timeserial;
|
|
379
326
|
}
|
|
380
327
|
|
|
381
|
-
/**
|
|
382
|
-
* 期間の値を別の単位に換算する
|
|
383
|
-
* 月と年は固定長(1か月 = 30日、1年 = 365日)として換算する
|
|
384
|
-
*
|
|
385
|
-
* @example
|
|
386
|
-
* convertTimeUnit(1, 'hours', 'milliseconds'); // 3600000
|
|
387
|
-
*
|
|
388
|
-
* @param {number} value
|
|
389
|
-
* @param {TimeUnit} inputUnit
|
|
390
|
-
* @param {TimeUnit} outputUnit
|
|
391
|
-
* @returns {number}
|
|
392
|
-
*/
|
|
393
|
-
export function convertTimeUnit(value: number, inputUnit: TimeUnit, outputUnit: TimeUnit): number {
|
|
394
|
-
return LuxonDuration.fromObject({ [inputUnit]: value }).as(outputUnit);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
328
|
/**
|
|
398
329
|
* timezone が at の時点で夏時間かどうかを返す
|
|
399
330
|
* at を省略した場合は現在時刻で判定する。at が解釈できない場合は false を返す
|
|
@@ -404,12 +335,8 @@ export function convertTimeUnit(value: number, inputUnit: TimeUnit, outputUnit:
|
|
|
404
335
|
* @returns {boolean}
|
|
405
336
|
*/
|
|
406
337
|
export function isInDST(timezone: string, at?: DateInput): boolean {
|
|
407
|
-
const d = at === undefined ?
|
|
408
|
-
|
|
409
|
-
return false;
|
|
410
|
-
}
|
|
411
|
-
assertZone(d);
|
|
412
|
-
return d.isInDST;
|
|
338
|
+
const d = at === undefined ? ZonedDateTime.now(timezone) : ZonedDateTime.parse(at)?.setZone(timezone);
|
|
339
|
+
return d?.isInDST ?? false;
|
|
413
340
|
}
|
|
414
341
|
|
|
415
342
|
/**
|
|
@@ -426,9 +353,8 @@ export function getTimezoneAbbr(timezone: string, options?: TimezoneAbbrOptions)
|
|
|
426
353
|
return null;
|
|
427
354
|
}
|
|
428
355
|
if (definition.daylight) {
|
|
429
|
-
const d =
|
|
430
|
-
|
|
431
|
-
if (d.isInDST) {
|
|
356
|
+
const d = ZonedDateTime.parse(options?.at ?? new Date())?.setZone(timezone);
|
|
357
|
+
if (d?.isInDST) {
|
|
432
358
|
return definition.daylight;
|
|
433
359
|
}
|
|
434
360
|
}
|
package/src/html-util.ts
CHANGED
|
@@ -57,24 +57,33 @@ const toStyleString = (value: HtmlStyleValue): string => {
|
|
|
57
57
|
.join('; ');
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
+
/** diffForWebの既定の文字色 */
|
|
61
|
+
const DIFF_STYLES = {
|
|
62
|
+
added: 'color: var(--dwui-color-text-diff-added, light-dark(#006400, rgb(121, 227, 121)))',
|
|
63
|
+
removed: 'color: var(--dwui-color-text-diff-removed, light-dark(#ff0000, rgb(222, 109, 109)))',
|
|
64
|
+
same: 'color: var(--dwui-color-text-diff-same, light-dark(#838383, #808080))'
|
|
65
|
+
};
|
|
66
|
+
|
|
60
67
|
/**
|
|
61
|
-
*
|
|
68
|
+
* 値をエスケープしたタグを返す
|
|
62
69
|
*
|
|
70
|
+
* @param {string} tagName
|
|
63
71
|
* @param {string} value
|
|
64
72
|
* @param {HtmlTagOptions} [options]
|
|
73
|
+
* @param {string} [defaultStyle] optionsのstyleより前に出力するstyle
|
|
65
74
|
* @returns {string}
|
|
66
75
|
*/
|
|
67
|
-
const
|
|
76
|
+
const toElement = (tagName: string, value: string, options?: HtmlTagOptions, defaultStyle?: string): string => {
|
|
68
77
|
let attributes = '';
|
|
69
78
|
const className = options?.class == null ? '' : toClassString(options.class);
|
|
70
79
|
if (className) {
|
|
71
80
|
attributes += ` class="${escapeHtml(className)}"`;
|
|
72
81
|
}
|
|
73
|
-
const style = options?.style == null ? '' : toStyleString(options.style);
|
|
82
|
+
const style = [defaultStyle, options?.style == null ? '' : toStyleString(options.style)].filter(Boolean).join('; ');
|
|
74
83
|
if (style) {
|
|
75
84
|
attributes += ` style="${escapeHtml(style)}"`;
|
|
76
85
|
}
|
|
77
|
-
return
|
|
86
|
+
return `<${tagName}${attributes}>${escapeHtml(value)}</${tagName}>`;
|
|
78
87
|
};
|
|
79
88
|
|
|
80
89
|
/**
|
|
@@ -127,16 +136,16 @@ export function formatJsonStringForWeb(value: any, options?: FormatJsonStringOpt
|
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
/**
|
|
130
|
-
* 文字列の中で一致したワードを
|
|
139
|
+
* 文字列の中で一致したワードをmarkタグで囲んだHTML文字列を返す
|
|
131
140
|
* オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能
|
|
132
141
|
*
|
|
133
142
|
* 例)
|
|
134
143
|
* HtmlUtil.highlightWord('This is a test message', 'test', { class: 'highlight' });
|
|
135
|
-
* → 'This is a <
|
|
144
|
+
* → 'This is a <mark class="highlight">test</mark> message'
|
|
136
145
|
*
|
|
137
146
|
* @param {string | null | undefined} value
|
|
138
147
|
* @param {string | null | undefined} word
|
|
139
|
-
* @param {*} [options]
|
|
148
|
+
* @param {*} [options] markタグに付与するclass, styleのほか、以下を指定できる
|
|
140
149
|
* ├ class string | string[] | Record<string, boolean>
|
|
141
150
|
* ├ style string | Record<string, string | number>
|
|
142
151
|
* ├ caseInsensitive boolean trueを指定した場合、大文字小文字を区別しない
|
|
@@ -165,7 +174,7 @@ export function highlightWord(
|
|
|
165
174
|
// キャプチャグループで分割すると、奇数番目の要素が一致した部分になる
|
|
166
175
|
const highlight = (text: string): string => text
|
|
167
176
|
.split(regex)
|
|
168
|
-
.map((part, i) => i % 2 === 0 ? toHtml(part) :
|
|
177
|
+
.map((part, i) => i % 2 === 0 ? toHtml(part) : toElement('mark', part, options))
|
|
169
178
|
.join('');
|
|
170
179
|
|
|
171
180
|
if (!options?.html) {
|
|
@@ -181,7 +190,8 @@ export function highlightWord(
|
|
|
181
190
|
|
|
182
191
|
/**
|
|
183
192
|
* 文字列を1文字ずつ比較し、差分をspanタグで囲んだHTML文字列を返す
|
|
184
|
-
*
|
|
193
|
+
* 追加・削除・一致の部分ごとに既定の文字色を持つ。文字色はCSS変数(--dwui-color-text-diff-added / --dwui-color-text-diff-removed / --dwui-color-text-diff-same)で変更できる
|
|
194
|
+
* 追加・削除・一致の部分ごとに、spanタグに付与するclass, styleを指定できる。styleは既定の文字色より後に出力する
|
|
185
195
|
* 入力文字列はプレーンなテキストであるとみなす
|
|
186
196
|
* 出力される文字列は、diffで埋め込まれるHTMLタグ以外はHTMLエスケープされ、HTMLセーフな文字列となる
|
|
187
197
|
*
|
|
@@ -204,11 +214,11 @@ export function diffForWeb(text1: string | null | undefined, text2: string | nul
|
|
|
204
214
|
let html = '';
|
|
205
215
|
for (const change of changes) {
|
|
206
216
|
if (change.added) {
|
|
207
|
-
html +=
|
|
217
|
+
html += toElement('span', change.value, options?.added, DIFF_STYLES.added);
|
|
208
218
|
} else if (change.removed) {
|
|
209
|
-
html +=
|
|
219
|
+
html += toElement('span', change.value, options?.removed, DIFF_STYLES.removed);
|
|
210
220
|
} else {
|
|
211
|
-
html +=
|
|
221
|
+
html += toElement('span', change.value, options?.same, DIFF_STYLES.same);
|
|
212
222
|
}
|
|
213
223
|
}
|
|
214
224
|
return html;
|
package/src/index.ts
CHANGED
package/src/json-util.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JSON.parseのreviverが第3引数で受け取る情報
|
|
3
3
|
*/
|
|
4
|
-
interface JsonReviverContext {
|
|
4
|
+
export interface JsonReviverContext {
|
|
5
5
|
/** プリミティブ値のJSON上の表記 */
|
|
6
6
|
source?: string;
|
|
7
7
|
}
|
|
@@ -12,17 +12,20 @@ const INTEGER_LITERAL = /^-?\d+$/;
|
|
|
12
12
|
* JSON文字列をパースする
|
|
13
13
|
* Number.MIN_SAFE_INTEGER〜Number.MAX_SAFE_INTEGERの範囲外の整数はnumberに変換すると桁落ちするため、JSON上の表記のまま文字列で返す
|
|
14
14
|
* そのため、同じ項目でも値の大きさによってnumberとstringが混在する
|
|
15
|
+
* reviverには、範囲外の整数を文字列にした後の値を渡す
|
|
15
16
|
*
|
|
16
17
|
* @param {string} source
|
|
18
|
+
* @param {(this: any, key: string, value: any, context?: JsonReviverContext) => any} [reviver]
|
|
17
19
|
* @returns {T}
|
|
18
20
|
*/
|
|
19
|
-
export function parse<T = any>(source: string): T {
|
|
20
|
-
return JSON.parse(source, (
|
|
21
|
+
export function parse<T = any>(source: string, reviver?: (this: any, key: string, value: any, context?: JsonReviverContext) => any): T {
|
|
22
|
+
return JSON.parse(source, function(this: any, key: string, value: any, context?: JsonReviverContext) {
|
|
21
23
|
const literal = context?.source;
|
|
24
|
+
let result = value;
|
|
22
25
|
if (typeof value === 'number' && !Number.isSafeInteger(value) && literal && INTEGER_LITERAL.test(literal)) {
|
|
23
|
-
|
|
26
|
+
result = literal;
|
|
24
27
|
}
|
|
25
|
-
return
|
|
28
|
+
return reviver ? reviver.call(this, key, result, context) : result;
|
|
26
29
|
}) as T;
|
|
27
30
|
}
|
|
28
31
|
|