// @ts-nocheck let _maskingPidMap = null; export function setMaskingPidMap(pidMap) { _maskingPidMap = (pidMap && typeof pidMap === 'object') ? pidMap : null; } export function clearMaskingPidMap() { _maskingPidMap = null; } function _unmaskText(s) { if (!_maskingPidMap) return s; let r = String(s); r = r.replace(/\[(?:NAME|STATION|CAR|TRAIN|TEAM):(emp_[a-z0-9]+)\]/gi, (m, pid) => { const e = _maskingPidMap[pid]; return e?.name ? e.name : m; }); r = r.replace(/\[ID:(emp_[a-z0-9]+)\]/gi, (m, pid) => { const e = _maskingPidMap[pid]; return e?.id != null ? String(e.id) : m; }); r = r.replace(/\bemp_[a-z0-9]+\b/gi, (m) => { const e = _maskingPidMap[m]; return e?.id != null ? String(e.id) : m; }); return r; } export function render(text) { if (!text) return ''; const unmasked = _maskingPidMap ? _unmaskText(text) : text; let s = escapeHtml(normalizeTableMarkup(unmasked)); const codeBlocks = []; s = s.replace(/```(\w*)\n?([\s\S]*?)```/g, (m, lang, code) => { const idx = codeBlocks.length; codeBlocks.push(`
${code.trim()}
`); return `\x00CB${idx}\x00`; }); const inlineCodes = []; s = s.replace(/`([^`\n]+)`/g, (m, code) => { const idx = inlineCodes.length; inlineCodes.push(`${code}`); return `\x00IC${idx}\x00`; }); s = s.replace(/^### (.+)$/gm, '

$1

'); s = s.replace(/^## (.+)$/gm, '

$1

'); s = s.replace(/^# (.+)$/gm, '

$1

'); s = s.replace(/\*\*([^*\n]+)\*\*/g, '$1'); s = s.replace(/(^|[^*])\*([^*\n]+)\*(?!\*)/g, '$1$2'); s = s.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g, '$1'); s = renderBlocks(s); s = s.replace(/\x00CB(\d+)\x00/g, (m, idx) => codeBlocks[idx]); s = s.replace(/\x00IC(\d+)\x00/g, (m, idx) => inlineCodes[idx]); return s; } function renderBlocks(s) { const lines = s.split('\n'); const out = []; let i = 0; while (i < lines.length) { const line = lines[i]; if (!line.trim()) { i++; continue; } if (/^\x00CB\d+\x00$/.test(line.trim())) { out.push(line.trim()); i++; continue; } if (isListItemLine(line)) { const collected = []; while (i < lines.length) { const L = lines[i]; if (!L.trim()) { let j = i + 1; while (j < lines.length && !lines[j].trim()) j++; if (j < lines.length && isListItemLine(lines[j])) { i = j; continue; } break; } if (isListItemLine(L) || isListContinuation(L)) { collected.push(L); i++; continue; } break; } out.push(renderList(collected)); continue; } if (/^> /.test(line)) { const quoteLines = []; while (i < lines.length && /^> /.test(lines[i])) { quoteLines.push(lines[i].replace(/^> /, '')); i++; } out.push(`
${quoteLines.join('
')}
`); continue; } if (isTableRow(line) && i + 1 < lines.length) { const next = lines[i + 1]; if (isTableSeparator(next) || isImplicitTableBody(line, next)) { const headerLine = lines[i]; let separatorLine = next; i += 1; if (isTableSeparator(next)) { i += 1; } else { const cols = parseTableRow(headerLine).length; separatorLine = '|' + Array(cols).fill(' --- ').join('|') + '|'; } const bodyLines = []; while (i < lines.length && isTableRow(lines[i])) { bodyLines.push(lines[i]); i++; } out.push(renderTable(headerLine, separatorLine, bodyLines)); continue; } } const para = []; while (i < lines.length) { const L = lines[i]; if (!L.trim()) break; if (isListItemLine(L)) break; if (/^> /.test(L)) break; if (/^\x00CB\d+\x00$/.test(L.trim())) break; if (isTableRow(L) && i + 1 < lines.length && (isTableSeparator(lines[i + 1]) || isImplicitTableBody(L, lines[i + 1]))) break; if (/^/.test(L)) { if (para.length) break; out.push(L); i++; continue; } para.push(L); i++; } if (para.length) { if (para.every(l => /^/.test(l))) { out.push(para.join('\n')); } else { out.push(`

${para.join('
')}

`); } } } return out.join('\n'); } function isListItemLine(line) { return /^(\s*)([-*]|\d+\.) /.test(line); } function normalizeTableMarkup(text) { return String(text || '') .split('\n') .map((line) => { if (!/[||]/.test(line)) return line; return line .replace(/\uFF5C/g, '|') .replace(/[-—–]/g, '-'); }) .join('\n'); } function isTableRow(line) { if (!line) return false; const trimmed = line.trim(); if (!trimmed.includes('|')) return false; const cells = parseTableRow(trimmed); return cells.length >= 2; } function isImplicitTableBody(headerLine, nextLine) { if (!isTableRow(headerLine) || !isTableRow(nextLine) || isTableSeparator(nextLine)) return false; const a = parseTableRow(headerLine); const b = parseTableRow(nextLine); return a.length >= 2 && a.length === b.length; } function isTableSeparator(line) { if (!line) return false; const trimmed = line.trim(); if (!trimmed.includes('|') || !trimmed.includes('-')) return false; if (!/^[\s|:\-]+$/.test(trimmed)) return false; const cells = parseTableRow(trimmed); return cells.length >= 2 && cells.every(c => /^:?-+:?$/.test(c.trim())); } function parseTableRow(line) { return line.trim() .replace(/^\|/, '') .replace(/\|$/, '') .split('|') .map(c => c.trim()); } function renderTable(headerLine, separatorLine, bodyLines) { const headers = parseTableRow(headerLine); const separators = parseTableRow(separatorLine); const aligns = separators.map(sep => { const s = sep.trim(); if (/^:-+$/.test(s)) return 'left'; if (/^-+:$/.test(s)) return 'right'; if (/^:-+:$/.test(s)) return 'center'; return null; }); const cellTag = (isHeader, idx) => { const align = aligns[idx]; const style = align ? ` style="text-align:${align}"` : ''; const tag = isHeader ? 'th' : 'td'; return `<${tag}${style}>`; }; const closeTag = (isHeader) => isHeader ? '' : ''; let html = ''; headers.forEach((h, idx) => { html += `${cellTag(true, idx)}${h}${closeTag(true)}`; }); html += ''; bodyLines.forEach(line => { const cells = parseTableRow(line); html += ''; const max = Math.max(headers.length, cells.length); for (let idx = 0; idx < max; idx++) { html += `${cellTag(false, idx)}${cells[idx] || ''}${closeTag(false)}`; } html += ''; }); html += '
'; return html; } function isListContinuation(line) { return /^\s{2,}\S/.test(line) && !isListItemLine(line); } function parseListMarker(line) { const m = line.match(/^(\s*)([-*]|\d+\.) (.*)$/); if (!m) return null; return { indent: m[1].length, ordered: /^\d+\.$/.test(m[2]), content: m[3], }; } function renderList(lines) { const items = []; for (const line of lines) { const parsed = parseListMarker(line); if (parsed) { items.push({ ...parsed, children: [] }); } else if (items.length && isListContinuation(line)) { items[items.length - 1].content += '
' + line.trim(); } } return renderListTree(items, 0); } function renderListTree(items, minIndent) { if (!items.length) return ''; const levelIndent = items[0].indent; const ordered = items[0].ordered; const tag = ordered ? 'ol' : 'ul'; const parts = []; let i = 0; while (i < items.length) { const item = items[i]; if (item.indent < minIndent) break; if (item.indent > levelIndent) { break; } if (item.indent < levelIndent) break; i++; const childStart = i; while (i < items.length && items[i].indent > levelIndent) i++; const children = items.slice(childStart, i); let html = `
  • ${item.content}`; if (children.length) { html += renderListTree(children, levelIndent + 1); } html += '
  • '; parts.push(html); } return `<${tag}>${parts.join('')}`; } function escapeHtml(s) { return String(s) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); }