mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			131 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { applyLocale } from './i18n.js';
 | 
						|
 | 
						|
/**
 | 
						|
 * @type {Map<string, function>}
 | 
						|
 * @description Cache for Handlebars templates.
 | 
						|
 */
 | 
						|
const TEMPLATE_CACHE = new Map();
 | 
						|
 | 
						|
/**
 | 
						|
 * Loads a URL content using XMLHttpRequest synchronously.
 | 
						|
 * @param {string} url URL to load synchronously
 | 
						|
 * @returns {string} Response text
 | 
						|
 */
 | 
						|
function getUrlSync(url) {
 | 
						|
    console.debug('Loading URL synchronously', url);
 | 
						|
    const request = new XMLHttpRequest();
 | 
						|
    request.open('GET', url, false); // `false` makes the request synchronous
 | 
						|
    request.send();
 | 
						|
 | 
						|
    if (request.status >= 200 && request.status < 300) {
 | 
						|
        return request.responseText;
 | 
						|
    }
 | 
						|
 | 
						|
    throw new Error(`Error loading ${url}: ${request.status} ${request.statusText}`);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Loads a URL content using XMLHttpRequest asynchronously.
 | 
						|
 * @param {string} url URL to load asynchronously
 | 
						|
 * @returns {Promise<string>} Response text
 | 
						|
 */
 | 
						|
function getUrlAsync(url) {
 | 
						|
    return new Promise((resolve, reject) => {
 | 
						|
        const request = new XMLHttpRequest();
 | 
						|
        request.open('GET', url, true);
 | 
						|
        request.onload = () => {
 | 
						|
            if (request.status >= 200 && request.status < 300) {
 | 
						|
                resolve(request.responseText);
 | 
						|
            } else {
 | 
						|
                reject(new Error(`Error loading ${url}: ${request.status} ${request.statusText}`));
 | 
						|
            }
 | 
						|
        };
 | 
						|
        request.onerror = () => {
 | 
						|
            reject(new Error(`Error loading ${url}: ${request.status} ${request.statusText}`));
 | 
						|
        };
 | 
						|
        request.send();
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Renders a Handlebars template asynchronously.
 | 
						|
 * @param {string} templateId ID of the template to render
 | 
						|
 * @param {Record<string, any>} templateData The data to pass to the template
 | 
						|
 * @param {boolean} sanitize Should the template be sanitized with DOMPurify
 | 
						|
 * @param {boolean} localize Should the template be localized
 | 
						|
 * @param {boolean} fullPath Should the template ID be treated as a full path or a relative path
 | 
						|
 * @returns {Promise<string>} Rendered template
 | 
						|
 */
 | 
						|
export async function renderTemplateAsync(templateId, templateData = {}, sanitize = true, localize = true, fullPath = false) {
 | 
						|
    async function fetchTemplateAsync(pathToTemplate) {
 | 
						|
        let template = TEMPLATE_CACHE.get(pathToTemplate);
 | 
						|
        if (!template) {
 | 
						|
            const templateContent = await getUrlAsync(pathToTemplate);
 | 
						|
            template = Handlebars.compile(templateContent);
 | 
						|
            TEMPLATE_CACHE.set(pathToTemplate, template);
 | 
						|
        }
 | 
						|
        return template;
 | 
						|
    }
 | 
						|
 | 
						|
    try {
 | 
						|
        const pathToTemplate = fullPath ? templateId : `/scripts/templates/${templateId}.html`;
 | 
						|
        const template = await fetchTemplateAsync(pathToTemplate);
 | 
						|
        let result = template(templateData);
 | 
						|
 | 
						|
        if (sanitize) {
 | 
						|
            result = DOMPurify.sanitize(result);
 | 
						|
        }
 | 
						|
 | 
						|
        if (localize) {
 | 
						|
            result = applyLocale(result);
 | 
						|
        }
 | 
						|
 | 
						|
        return result;
 | 
						|
    } catch (err) {
 | 
						|
        console.error('Error rendering template', templateId, templateData, err);
 | 
						|
        toastr.error('Check the DevTools console for more information.', 'Error rendering template');
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Renders a Handlebars template synchronously.
 | 
						|
 * @param {string} templateId ID of the template to render
 | 
						|
 * @param {Record<string, any>} templateData The data to pass to the template
 | 
						|
 * @param {boolean} sanitize Should the template be sanitized with DOMPurify
 | 
						|
 * @param {boolean} localize Should the template be localized
 | 
						|
 * @param {boolean} fullPath Should the template ID be treated as a full path or a relative path
 | 
						|
 * @returns {string} Rendered template
 | 
						|
 *
 | 
						|
 * @deprecated Use renderTemplateAsync instead.
 | 
						|
 */
 | 
						|
export function renderTemplate(templateId, templateData = {}, sanitize = true, localize = true, fullPath = false) {
 | 
						|
    function fetchTemplateSync(pathToTemplate) {
 | 
						|
        let template = TEMPLATE_CACHE.get(pathToTemplate);
 | 
						|
        if (!template) {
 | 
						|
            const templateContent = getUrlSync(pathToTemplate);
 | 
						|
            template = Handlebars.compile(templateContent);
 | 
						|
            TEMPLATE_CACHE.set(pathToTemplate, template);
 | 
						|
        }
 | 
						|
        return template;
 | 
						|
    }
 | 
						|
 | 
						|
    try {
 | 
						|
        const pathToTemplate = fullPath ? templateId : `/scripts/templates/${templateId}.html`;
 | 
						|
        const template = fetchTemplateSync(pathToTemplate);
 | 
						|
        let result = template(templateData);
 | 
						|
 | 
						|
        if (sanitize) {
 | 
						|
            result = DOMPurify.sanitize(result);
 | 
						|
        }
 | 
						|
 | 
						|
        if (localize) {
 | 
						|
            result = applyLocale(result);
 | 
						|
        }
 | 
						|
 | 
						|
        return result;
 | 
						|
    } catch (err) {
 | 
						|
        console.error('Error rendering template', templateId, templateData, err);
 | 
						|
        toastr.error('Check the DevTools console for more information.', 'Error rendering template');
 | 
						|
    }
 | 
						|
}
 |