@kylincloud/flamegraph 0.35.23 → 0.35.24
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/CHANGELOG.md +13 -0
- package/dist/FlameGraph/FlameGraphComponent/FlamegraphBreadcrumb.d.ts +16 -0
- package/dist/FlameGraph/FlameGraphComponent/FlamegraphBreadcrumb.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/Flamegraph_render.d.ts +1 -0
- package/dist/FlameGraph/FlameGraphComponent/Flamegraph_render.d.ts.map +1 -1
- package/dist/FlameGraph/FlameGraphComponent/index.d.ts +13 -0
- package/dist/FlameGraph/FlameGraphComponent/index.d.ts.map +1 -1
- package/dist/FlameGraph/FlameGraphRenderer.d.ts +9 -1
- package/dist/FlameGraph/FlameGraphRenderer.d.ts.map +1 -1
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/format/format.d.ts +14 -0
- package/dist/format/format.d.ts.map +1 -1
- package/dist/i18n.d.ts +7 -0
- package/dist/i18n.d.ts.map +1 -1
- package/dist/index.cjs.js +3 -3
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +4 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.node.cjs.js +4 -4
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.node.esm.js +4 -4
- package/dist/index.node.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/FlameGraph/FlameGraphComponent/FlamegraphBreadcrumb.module.scss +106 -0
- package/src/FlameGraph/FlameGraphComponent/FlamegraphBreadcrumb.tsx +98 -0
- package/src/FlameGraph/FlameGraphComponent/Flamegraph_render.ts +23 -21
- package/src/FlameGraph/FlameGraphComponent/index.tsx +33 -1
- package/src/FlameGraph/FlameGraphRenderer.tsx +144 -3
- package/src/Tooltip/Tooltip.tsx +1 -75
- package/src/format/format.ts +98 -0
- package/src/i18n.tsx +27 -0
package/src/format/format.ts
CHANGED
|
@@ -5,6 +5,104 @@ export function numberWithCommas(x: number): string {
|
|
|
5
5
|
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
type NumericWithUnit = {
|
|
9
|
+
value: number;
|
|
10
|
+
unit: string;
|
|
11
|
+
hasLessThan: boolean;
|
|
12
|
+
sign: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function parseNumericWithUnit(
|
|
16
|
+
input?: string | number
|
|
17
|
+
): NumericWithUnit | null {
|
|
18
|
+
if (input == null) return null;
|
|
19
|
+
|
|
20
|
+
if (typeof input === 'number') {
|
|
21
|
+
return { value: input, unit: '', hasLessThan: false, sign: '' };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let s = String(input).trim().replace(/\u2212/g, '-');
|
|
25
|
+
if (!s) return null;
|
|
26
|
+
|
|
27
|
+
let hasLessThan = false;
|
|
28
|
+
if (s.startsWith('<')) {
|
|
29
|
+
hasLessThan = true;
|
|
30
|
+
s = s.slice(1).trim();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const m = s.match(/^([+\-]?)(\d*\.?\d+)\s*(.*)$/);
|
|
34
|
+
if (!m) return null;
|
|
35
|
+
|
|
36
|
+
const sign = m[1] || '';
|
|
37
|
+
const numStr = m[2];
|
|
38
|
+
const unit = (m[3] || '').trim();
|
|
39
|
+
|
|
40
|
+
const value = parseFloat(numStr);
|
|
41
|
+
if (!Number.isFinite(value)) return null;
|
|
42
|
+
|
|
43
|
+
return { value, unit, hasLessThan, sign };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function localizeDurationString(
|
|
47
|
+
input?: string,
|
|
48
|
+
isZh = false
|
|
49
|
+
): string | undefined {
|
|
50
|
+
if (!input || !isZh) return input;
|
|
51
|
+
|
|
52
|
+
const parsed = parseNumericWithUnit(input);
|
|
53
|
+
if (!parsed) return input;
|
|
54
|
+
|
|
55
|
+
const { unit } = parsed;
|
|
56
|
+
|
|
57
|
+
let unitZh = unit;
|
|
58
|
+
const u = unit.toLowerCase();
|
|
59
|
+
|
|
60
|
+
if (u === 'ms') unitZh = '毫秒';
|
|
61
|
+
else if (u === 'μs' || u === 'µs' || u === 'us') unitZh = '微秒';
|
|
62
|
+
else if (u === 'second' || u === 'seconds') unitZh = '秒';
|
|
63
|
+
else if (u === 'minute' || u === 'minutes' || u === 'min' || u === 'mins')
|
|
64
|
+
unitZh = '分钟';
|
|
65
|
+
else if (u === 'hour' || u === 'hours') unitZh = '小时';
|
|
66
|
+
else if (u === 'day' || u === 'days') unitZh = '天';
|
|
67
|
+
else if (u === 'month' || u === 'months') unitZh = '月';
|
|
68
|
+
else if (u === 'year' || u === 'years') unitZh = '年';
|
|
69
|
+
|
|
70
|
+
const m = String(input).match(/^([<\s]*)([+\-]?\d*\.?\d+)(.*)$/);
|
|
71
|
+
if (!m) return input;
|
|
72
|
+
|
|
73
|
+
const prefix = m[1] || '';
|
|
74
|
+
const numberPart = m[2] || '';
|
|
75
|
+
|
|
76
|
+
return `${prefix}${numberPart} ${unitZh}`.trim();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export type SampleCountFormat = Array<{ value: number; label: string }>;
|
|
80
|
+
|
|
81
|
+
const defaultSampleCountFormat: SampleCountFormat = [
|
|
82
|
+
{ value: 1e15, label: 'Quad' },
|
|
83
|
+
{ value: 1e12, label: 'Tri' },
|
|
84
|
+
{ value: 1e9, label: 'B' },
|
|
85
|
+
{ value: 1e6, label: 'M' },
|
|
86
|
+
{ value: 1e3, label: 'K' },
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
export function formatSampleCount(
|
|
90
|
+
value: number,
|
|
91
|
+
format: SampleCountFormat = defaultSampleCountFormat
|
|
92
|
+
): string {
|
|
93
|
+
const absValue = Math.abs(value);
|
|
94
|
+
for (const { value: threshold, label } of format) {
|
|
95
|
+
if (absValue >= threshold) {
|
|
96
|
+
const scaled = value / threshold;
|
|
97
|
+
const fixed = scaled.toFixed(2);
|
|
98
|
+
const trimmed = fixed.replace(/\.?0+$/, '');
|
|
99
|
+
return `${trimmed} ${label}`;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return numberWithCommas(value);
|
|
104
|
+
}
|
|
105
|
+
|
|
8
106
|
export function formatPercent(ratio: number) {
|
|
9
107
|
const percent = ratioToPercent(ratio);
|
|
10
108
|
return `${percent}%`;
|
package/src/i18n.tsx
CHANGED
|
@@ -77,6 +77,11 @@ export type FlamegraphMessages = {
|
|
|
77
77
|
// 火焰图聚焦时的 collapsed 提示
|
|
78
78
|
collapsedLevelsSingular: string; // "total (1 level collapsed)"
|
|
79
79
|
collapsedLevelsPlural: string; // "total (n levels collapsed)"
|
|
80
|
+
|
|
81
|
+
// Breadcrumb
|
|
82
|
+
ofTotal: string;
|
|
83
|
+
clearFocus: string;
|
|
84
|
+
sampleCountFormat: Array<{ value: number; label: string }>;
|
|
80
85
|
};
|
|
81
86
|
|
|
82
87
|
const defaultTooltipUnitTitles: Record<Units, TooltipUnitMessages> = {
|
|
@@ -235,6 +240,17 @@ export const defaultMessages: FlamegraphMessages = {
|
|
|
235
240
|
// 火焰图聚焦时的 collapsed 提示
|
|
236
241
|
collapsedLevelsSingular: 'total (1 level collapsed)',
|
|
237
242
|
collapsedLevelsPlural: 'total ({n} levels collapsed)',
|
|
243
|
+
|
|
244
|
+
// Breadcrumb
|
|
245
|
+
ofTotal: 'of total',
|
|
246
|
+
clearFocus: 'Clear focus',
|
|
247
|
+
sampleCountFormat: [
|
|
248
|
+
{ value: 1e15, label: 'Quad' },
|
|
249
|
+
{ value: 1e12, label: 'Tri' },
|
|
250
|
+
{ value: 1e9, label: 'B' },
|
|
251
|
+
{ value: 1e6, label: 'M' },
|
|
252
|
+
{ value: 1e3, label: 'K' },
|
|
253
|
+
],
|
|
238
254
|
};
|
|
239
255
|
|
|
240
256
|
export const zhCNMessages: FlamegraphMessages = {
|
|
@@ -298,9 +314,20 @@ export const zhCNMessages: FlamegraphMessages = {
|
|
|
298
314
|
// 火焰图聚焦时的 collapsed 提示
|
|
299
315
|
collapsedLevelsSingular: '总计(已折叠 1 层)',
|
|
300
316
|
collapsedLevelsPlural: '总计(已折叠 {n} 层)',
|
|
317
|
+
|
|
318
|
+
// Breadcrumb
|
|
319
|
+
ofTotal: '占总量',
|
|
320
|
+
clearFocus: '清除聚焦',
|
|
321
|
+
sampleCountFormat: [
|
|
322
|
+
{ value: 1e12, label: '兆' },
|
|
323
|
+
{ value: 1e8, label: '亿' },
|
|
324
|
+
{ value: 1e4, label: '万' },
|
|
325
|
+
{ value: 1e3, label: '千' },
|
|
326
|
+
],
|
|
301
327
|
};
|
|
302
328
|
|
|
303
329
|
const I18nContext = createContext<FlamegraphMessages>(defaultMessages);
|
|
330
|
+
export const FlamegraphI18nContext = I18nContext;
|
|
304
331
|
|
|
305
332
|
export type FlamegraphI18nProviderProps = {
|
|
306
333
|
messages?: Partial<FlamegraphMessages>;
|