mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-07-30 11:55:49 +00:00
3d87032881
狭い画面だと変な場所で自動改行されて崩れるため
118 lines
4.4 KiB
TypeScript
118 lines
4.4 KiB
TypeScript
/*
|
||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||
* SPDX-License-Identifier: AGPL-3.0-only
|
||
*/
|
||
|
||
const numberFormatter = new Intl.NumberFormat('en-US', {
|
||
maximumFractionDigits: 1,
|
||
});
|
||
|
||
export function escapeLatex(text: string) {
|
||
return text
|
||
.replaceAll('\\', '\\\\')
|
||
.replaceAll('{', '\\{')
|
||
.replaceAll('}', '\\}')
|
||
.replaceAll('%', '\\%');
|
||
}
|
||
|
||
export function escapeMdTableCell(value: string) {
|
||
return String(value).replaceAll('|', '\\|').replaceAll('\n', '<br>');
|
||
}
|
||
|
||
export function escapeHtml(value: unknown) {
|
||
return String(value ?? '')
|
||
.replaceAll('&', '&')
|
||
.replaceAll('<', '<')
|
||
.replaceAll('>', '>')
|
||
.replaceAll('"', '"')
|
||
.replaceAll('\'', ''');
|
||
}
|
||
|
||
export function formatNumber(value: number) {
|
||
return numberFormatter.format(value);
|
||
}
|
||
|
||
export function formatBytes(value: number) {
|
||
if (value === 0) return '0 B'; // nbspにすること
|
||
const units = ['B', 'KB', 'MB', 'GB'];
|
||
let unitIndex = 0;
|
||
let size = value;
|
||
while (size >= 1000 && unitIndex < units.length - 1) {
|
||
size /= 1000;
|
||
unitIndex += 1;
|
||
}
|
||
|
||
const maximumFractionDigits = size >= 10 || unitIndex === 0 ? 0 : 1;
|
||
// eslint-disable-next-line no-irregular-whitespace
|
||
return `${numberFormatter.format(Number(size.toFixed(maximumFractionDigits)))} ${units[unitIndex]}`; // nbspにすること
|
||
}
|
||
|
||
/**
|
||
* KiB単位の値をMB表記にする。/proc 由来の値の表示に使う。
|
||
*/
|
||
export function formatKiBAsMb(valueKiB: number | null | undefined) {
|
||
if (valueKiB == null || !Number.isFinite(valueKiB)) return '-';
|
||
return `${formatNumber(valueKiB / 1000)} MB`;
|
||
}
|
||
|
||
export function formatPercent(value: number) {
|
||
return `${formatNumber(value)}%`;
|
||
}
|
||
|
||
export function formatMs(value: number | null | undefined) {
|
||
if (value == null || !Number.isFinite(value)) return '-';
|
||
if (value >= 1_000) return `${formatNumber(value / 1_000)} s`;
|
||
return `${formatNumber(value)} ms`;
|
||
}
|
||
|
||
export function formatSecondsAsMs(value: number | null | undefined) {
|
||
if (value == null || !Number.isFinite(value)) return '-';
|
||
return formatMs(value * 1_000);
|
||
}
|
||
|
||
/**
|
||
* 差分値を符号付きで整形する。`colorThreshold` 以上の変化があるときだけ色を付ける。
|
||
*/
|
||
export function formatColoredDelta(delta: number, text: (value: number) => string, colorThreshold = 0) {
|
||
if (delta === 0) return text(0);
|
||
const sign = delta > 0 ? '+' : '-';
|
||
if (Math.abs(delta) < colorThreshold) return `$\\text{${sign}${escapeLatex(text(Math.abs(delta))).replaceAll(' ', '~')}}$`; // "1 B"とかで1とBの間で自動改行させないためnbsp(~)にする
|
||
const color = delta > 0 ? 'orange' : 'green';
|
||
return `$\\color{${color}}{\\text{${sign}${escapeLatex(text(Math.abs(delta))).replaceAll(' ', '~')}}}$`; // "1 B"とかで1とBの間で自動改行させないためnbsp(~)にする
|
||
}
|
||
|
||
export function formatDeltaBytes(deltaBytes: number, colorThreshold = 0) {
|
||
return formatColoredDelta(deltaBytes, formatBytes, colorThreshold);
|
||
}
|
||
|
||
export function formatDeltaPercent(deltaPercent: number, colorThreshold = 0) {
|
||
return formatColoredDelta(deltaPercent, formatPercent, colorThreshold);
|
||
}
|
||
|
||
/**
|
||
* Markdownのテーブルセル内に置く差分パーセント。
|
||
* LaTeX由来の `\%` がMarkdownのエスケープで食われるため二重エスケープする。
|
||
*/
|
||
export function formatDeltaPercentInMdTable(deltaPercent: number, colorThreshold = 0) {
|
||
return formatDeltaPercent(deltaPercent, colorThreshold).replaceAll('\\%', '\\\\%');
|
||
}
|
||
|
||
export function calcAndFormatDeltaNumber(before: number | null | undefined, after: number | null | undefined, colorThreshold = 0) {
|
||
if (before == null || after == null) return '-';
|
||
return formatColoredDelta(after - before, formatNumber, colorThreshold);
|
||
}
|
||
|
||
export function calcAndFormatDeltaBytes(before: number | null | undefined, after: number | null | undefined, colorThreshold = 0) {
|
||
if (before == null || after == null) return '-';
|
||
return formatDeltaBytes(after - before, colorThreshold);
|
||
}
|
||
|
||
export function calcAndFormatDeltaPercent(before: number | null | undefined, after: number | null | undefined, colorThreshold = 0) {
|
||
if (before == null || before === 0 || after == null) return '-';
|
||
return formatDeltaPercent((after - before) / before * 100, colorThreshold);
|
||
}
|
||
|
||
export function calcAndFormatDeltaPercentInMdTable(before: number | null | undefined, after: number | null | undefined, colorThreshold = 0) {
|
||
return calcAndFormatDeltaPercent(before, after, colorThreshold).replaceAll('\\%', '\\\\%');
|
||
}
|