brief-rags-bench/static/js/utils/format.utils.js

151 lines
4.0 KiB
JavaScript

/**
* Format Utilities
*
* Функции для форматирования данных (время, текст, UUID).
*/
/**
* Генерация UUID v4
* @returns {string} UUID
*/
export function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0
const v = c === 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
})
}
/**
* Форматировать время в секундах в читаемый вид
* @param {number} seconds - Количество секунд
* @returns {string} Отформатированное время (например, "2.5 сек", "1 мин 30 сек")
*/
export function formatTime(seconds) {
if (seconds < 60) {
return `${seconds.toFixed(1)} сек`
}
const minutes = Math.floor(seconds / 60)
const secs = Math.floor(seconds % 60)
return `${minutes} мин ${secs} сек`
}
/**
* Форматировать ISO timestamp в локальное время
* @param {string} isoString - ISO строка времени
* @returns {string} Отформатированное локальное время
*/
export function formatTimestamp(isoString) {
try {
const date = new Date(isoString)
return date.toLocaleString('ru-RU', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
})
} catch (e) {
return isoString
}
}
/**
* Проверить является ли текст таблицей
* @param {string} text - Текст для проверки
* @returns {boolean} True если текст похож на таблицу
*/
export function isTableText(text) {
const lines = text.split('\n').filter(line => line.trim())
if (lines.length < 3) return false
// Проверить наличие разделителей
const hasSeparator = lines.some(line => /^[\s\-|+]+$/.test(line))
const hasPipes = lines.filter(line => line.includes('|')).length > 2
return hasSeparator || hasPipes
}
/**
* Парсинг текстовой таблицы в HTML
* @param {string} text - Текст таблицы
* @returns {string} HTML таблица
*/
export function parseTextTable(text) {
const lines = text.split('\n').filter(line => line.trim())
if (lines.length < 2) {
return `<pre>${escapeHtml(text)}</pre>`
}
let html = '<table class="parsed-table">'
let inHeader = true
for (const line of lines) {
// Skip separator lines
if (/^[\s\-|+]+$/.test(line)) {
inHeader = false
continue
}
// Parse cells
const cells = line.split('|')
.map(cell => cell.trim())
.filter((cell, i, arr) => i > 0 && i < arr.length - 1) // Remove first and last empty cells
if (cells.length === 0) continue
html += '<tr>'
const tag = inHeader ? 'th' : 'td'
for (const cell of cells) {
html += `<${tag}>${escapeHtml(cell)}</${tag}>`
}
html += '</tr>'
if (inHeader) {
inHeader = false
}
}
html += '</table>'
return html
}
/**
* Экранировать HTML спецсимволы
* @param {string} text - Исходный текст
* @returns {string} Экранированный текст
*/
export function escapeHtml(text) {
const div = document.createElement('div')
div.textContent = text
return div.innerHTML
}
/**
* Склонение числительных (русский язык)
* @param {number} count - Число
* @param {string} one - Форма для 1 (например, "вопрос")
* @param {string} few - Форма для 2-4 (например, "вопроса")
* @param {string} many - Форма для 5+ (например, "вопросов")
* @returns {string} Правильная форма
*/
export function pluralize(count, one, few, many) {
const mod10 = count % 10
const mod100 = count % 100
if (mod10 === 1 && mod100 !== 11) {
return one
}
if (mod10 >= 2 && mod10 <= 4 && (mod100 < 10 || mod100 >= 20)) {
return few
}
return many
}