// @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('')}${tag}>`;
}
function escapeHtml(s) {
return String(s)
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"');
}