mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	Add async template renderer
This commit is contained in:
		
							
								
								
									
										130
									
								
								public/scripts/templates.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								public/scripts/templates.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,130 @@ | ||||
| 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'); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user