html-to-json-rs
Version:
Package for converting HTML to JSON and JSON to HTML using Rust and WebAssembly.
95 lines (82 loc) • 3.17 kB
JavaScript
// Чистая JS-реализация: принимает JSON-строку или объект/массив объектов и возвращает HTML-строку
export const JsonToHtmlJs = (input) => {
// Экранирование текста
const escapeHtml = (str) => String(str)
.replace(/&(?!(?:[a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);)/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
// Экранирование для значений атрибутов (совпадает с escapeHtml)
const escapeAttr = (str) => escapeHtml(str);
// Рендер атрибутов: id, class, затем пары из attrs
const renderAttrs = (node) => {
const parts = [];
if (node && typeof node.id === 'string' && node.id.length > 0) {
parts.push(`id="${escapeAttr(node.id)}"`);
}
if (node && typeof node.class === 'string' && node.class.length > 0) {
parts.push(`class="${escapeAttr(node.class)}"`);
}
if (Array.isArray(node?.attrs)) {
for (const pair of node.attrs) {
if (!Array.isArray(pair) || pair.length < 2) continue;
const [k, v] = pair;
if (typeof k !== 'string') continue;
parts.push(`${k}="${escapeAttr(v)}"`);
}
}
return parts.length ? ' ' + parts.join(' ') : '';
};
// Рендер одного узла
const renderNode = (node) => {
if (!node || typeof node !== 'object') {
throw new Error('Invalid node: expected object');
}
const t = node.obj_type;
switch (t) {
case 'Element': {
const tag = node.name || '';
if (!tag) throw new Error('Element node must have a non-empty name');
const attrs = renderAttrs(node);
const children = Array.isArray(node.children) ? node.children.map(renderNode).join('') : '';
return `<${tag}${attrs}>${children}</${tag}>`;
}
case 'Text': {
const text = node.text != null ? node.text : '';
return escapeHtml(text);
}
case 'Comment': {
const text = node.text != null ? String(node.text) : '';
return `<!-- ${text} -->`;
}
case 'Doctype': {
const name = node.name || '';
if (!name) throw new Error('Doctype node must have a non-empty name');
return `<!DOCTYPE ${name}>`;
}
default:
throw new Error(`Unknown obj_type: ${t}`);
}
};
// Преобразуем вход к массиву узлов
const toArray = (value) => Array.isArray(value) ? value : [value];
if (typeof input === 'string') {
if (input.trim() === '') {
throw new Error('JSON must be a non-empty string');
}
let parsed;
try {
parsed = JSON.parse(input);
} catch (_e) {
throw new Error('JSON string is not valid!');
}
const nodes = toArray(parsed);
return nodes.map(renderNode).join('');
}
if (input && typeof input === 'object') {
const nodes = toArray(input);
return nodes.map(renderNode).join('');
}
throw new Error('Input must be a non-empty JSON string or a non-null object/array');
};