HTML templating in pure javascript that transforms JSON objects into HTML using JavaScript template objects
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Helper functions for text encoding, DOM hydration, component updates, and other common operations that support the json2html templating system.
Safely encode HTML strings to prevent XSS attacks and ensure proper display of user-generated content.
/**
* Encodes HTML string to text by escaping HTML entities
* @param {string|null|undefined} html - HTML string to encode, null, or undefined
* @returns {string} Text with HTML entities escaped, empty string for null/undefined
*/
function toText(html);Usage Examples:
const json2html = require('node-json2html');
// Basic HTML encoding
const userInput = '<script>alert("XSS")</script>';
const safe = json2html.toText(userInput);
console.log(safe);
// Result: "<script>alert("XSS")</script>"
// Handle various data types
console.log(json2html.toText("Hello & goodbye")); // "Hello & goodbye"
console.log(json2html.toText("<div>content</div>")); // "<div>content</div>"
console.log(json2html.toText(null)); // ""
console.log(json2html.toText(undefined)); // ""
console.log(json2html.toText(123)); // "123"
// Use in templates for safe text display
const template = {
"<>": "div",
"html": [
{ "<>": "h3", "text": "User Comment" },
{ "<>": "p", "html": json2html.toText("${userComment}") }
]
};
const data = { userComment: '<script>malicious()</script>' };
const html = json2html.render(data, template);
// User comment is safely encoded in outputAttach events and update triggers to existing DOM elements, typically used after server-side rendering or manual DOM manipulation.
/**
* Hydrates DOM elements with their events and update triggers
* @param {Element|Element[]} parent - Element or array of elements to hydrate
* @param {object} events - Event handlers object from iHTML rendering
* @param {object} triggers - Update triggers object from iHTML rendering
* @returns {object} this for method chaining
*/
function hydrate(parent, events, triggers);Usage Examples:
// Server-side rendering scenario
const template = {
"<>": "button",
"text": "Click me",
"onclick": function(e) { alert("Clicked!"); },
"#": "button-trigger"
};
// Get iHTML output with events and triggers
const ihtml = json2html.render({}, template, { output: "ihtml" });
// On the client side, inject the HTML
document.getElementById('container').innerHTML = ihtml.html;
// Then hydrate to attach events and triggers
const element = document.getElementById('container').firstElementChild;
json2html.hydrate(element, ihtml.events, ihtml.triggers);
// Now the button will work with click handlers and update triggers
// Hydrate multiple elements
const elements = document.querySelectorAll('.needs-hydration');
json2html.hydrate(Array.from(elements), ihtml.events, ihtml.triggers);Trigger dynamic updates of components that have been marked with trigger IDs.
/**
* Triggers component update by ID
* @param {string} id - Required trigger ID of component(s) to update
* @param {object} [obj] - Optional new data object to use for update
*/
function refresh(id, obj);
/**
* @deprecated Use refresh() instead
* Legacy alias for refresh function
*/
function trigger(id, obj);Usage Examples:
// Set up components with trigger IDs
const template = {
"<>": "div",
"#": "user-status", // Trigger ID
"class": "status-${status}",
"html": [
{ "<>": "span", "text": "${name}" },
{ "<>": "span", "class": "indicator", "text": "(${status})" }
]
};
const users = [
{ name: "Alice", status: "online" },
{ name: "Bob", status: "offline" }
];
// Render with DOM integration
document.getElementById('user-list').json2html(users, template);
// Update all elements with trigger ID "user-status"
setTimeout(() => {
json2html.refresh("user-status", [
{ name: "Alice", status: "busy" },
{ name: "Bob", status: "online" }
]);
}, 3000);
// Update with original data (uses stored reference)
setTimeout(() => {
users[0].status = "away";
json2html.refresh("user-status"); // Uses original users array
}, 6000);
// Multiple triggers for different components
const dashboardTemplate = {
"<>": "div",
"html": [
{
"<>": "div",
"#": "user-count",
"text": "Users: ${userCount}"
},
{
"<>": "div",
"#": "message-count",
"text": "Messages: ${messageCount}"
}
]
};
// Update specific parts independently
json2html.refresh("user-count", { userCount: 150 });
json2html.refresh("message-count", { messageCount: 1250 });Access the current version of the json2html library for compatibility checking and debugging.
/**
* Current version of the json2html library
* @type {string}
*/
const version: string;Usage Examples:
const json2html = require('node-json2html');
// Check library version
console.log('json2html version:', json2html.version); // "3.3.3"
// Version compatibility checking
function checkCompatibility() {
const requiredVersion = '3.0.0';
const currentVersion = json2html.version;
if (currentVersion < requiredVersion) {
throw new Error(`json2html ${requiredVersion} or higher required, found ${currentVersion}`);
}
}
// Feature detection based on version
function hasFeature(feature) {
const version = json2html.version;
const major = parseInt(version.split('.')[0]);
switch (feature) {
case 'iHTML':
return major >= 3;
case 'components':
return major >= 2;
default:
return true;
}
}
// Debug information
function getDebugInfo() {
return {
version: json2html.version,
userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'Node.js',
timestamp: new Date().toISOString()
};
}Utility functions handle various error conditions gracefully and provide meaningful feedback.
/**
* Common error scenarios and handling
*/
// toText handles null/undefined gracefully
json2html.toText(null); // Returns ""
json2html.toText(undefined); // Returns ""
// render handles missing data gracefully
json2html.render(null, template); // Returns ""
json2html.render(undefined, template); // Returns ""
// refresh handles missing trigger IDs gracefully
json2html.refresh("non-existent-id"); // No error, no action
// hydrate handles missing elements gracefully
json2html.hydrate(null, events, triggers); // No error, no actionError Handling Examples:
// Safe rendering with error handling
function safeRender(data, template, options = {}) {
try {
if (!data || !template) {
return '';
}
return json2html.render(data, template, options);
} catch (error) {
console.error('Rendering error:', error);
return '<div class="error">Rendering failed</div>';
}
}
// Safe text encoding
function safeText(input) {
if (input === null || input === undefined) {
return '';
}
return json2html.toText(String(input));
}
// Safe component updates with validation
function safeRefresh(triggerId, data) {
if (!triggerId || typeof triggerId !== 'string') {
console.warn('Invalid trigger ID provided to refresh');
return;
}
try {
json2html.refresh(triggerId, data);
} catch (error) {
console.error('Refresh error:', error);
}
}
// Safe hydration with element validation
function safeHydrate(elements, events, triggers) {
if (!elements) {
return;
}
const elementArray = Array.isArray(elements) ? elements : [elements];
const validElements = elementArray.filter(el => el && el.nodeType === Node.ELEMENT_NODE);
if (validElements.length > 0) {
json2html.hydrate(validElements, events || {}, triggers || {});
}
}Utility functions are optimized for performance but should be used appropriately for best results.
/**
* Performance best practices
*/
// Batch refresh operations instead of individual calls
// Good:
json2html.refresh("user-list", updatedUsers);
// Avoid:
users.forEach(user => {
json2html.refresh("user-" + user.id, user);
});
// Cache encoded text for reuse
const encodedTexts = new Map();
function getCachedText(input) {
if (!encodedTexts.has(input)) {
encodedTexts.set(input, json2html.toText(input));
}
return encodedTexts.get(input);
}
// Hydrate once after batch DOM updates
const ihtml = json2html.render(data, template, { output: "ihtml" });
container.innerHTML = ihtml.html;
json2html.hydrate(container, ihtml.events, ihtml.triggers);