151 lines
4.0 KiB
JavaScript
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
|
|
}
|