Files
Gustavo Santos e322cec92b chore: import coordenador (subtree)
git-subtree-dir: coordenador
git-subtree-mainline: facbe2e340
git-subtree-split: ce7af94d55
2026-10-01 14:25:55 -03:00

59 lines
1.6 KiB
JavaScript

const NAMED_ENTITIES = {
' ': ' ',
'&': '&',
'&lt;': '<',
'&gt;': '>',
'&quot;': '"',
'&#39;': "'",
'&apos;': "'",
};
const MAX_DECODE_ITERATIONS = 5;
function decodeEntitiesOnce(text) {
let result = text.replace(/&#(\d+);/g, (match, code) => {
const num = Number(code);
return Number.isFinite(num) ? String.fromCodePoint(num) : match;
});
result = result.replace(/&#x([0-9a-fA-F]+);/g, (match, hex) => {
const num = parseInt(hex, 16);
return Number.isFinite(num) ? String.fromCodePoint(num) : match;
});
for (const [entity, char] of Object.entries(NAMED_ENTITIES)) {
result = result.split(entity).join(char);
}
return result;
}
function stripHtmlTags(text) {
return text.replace(/<[^>]*>/g, ' ');
}
// Decodifica HTML/entities (inclusive escapado multiplas vezes, ate MAX_DECODE_ITERATIONS
// para nunca travar em loop) e remove tags -- sem apagar informacao (datas, nomes, numeros,
// codigos de erro, hostname, versao continuam intactos: nenhuma dessas regras mexe em texto
// que nao seja literalmente uma entidade HTML ou uma tag).
function normalizeGlpiText(rawText) {
if (rawText === null || rawText === undefined) return '';
let text = String(rawText);
for (let i = 0; i < MAX_DECODE_ITERATIONS; i += 1) {
const decoded = decodeEntitiesOnce(text);
if (decoded === text) break;
text = decoded;
}
text = stripHtmlTags(text);
text = text
.split('\n')
.map((line) => line.replace(/[ \t]+/g, ' ').trim())
.join('\n')
.replace(/\n{3,}/g, '\n\n')
.trim();
return text;
}
module.exports = { normalizeGlpiText, decodeEntitiesOnce, stripHtmlTags };