works
ae6e281d0c23ace350c56cdaa08c7699d7927ad9
3 files changed
src/NetproxySolution.Web/wwwroot/bench-template.htmlsrc/NetproxySolution.Web/wwwroot/template-fp.jssrc/NetproxySolution.Web/wwwroot/template-test.html
diff --git a/src/NetproxySolution.Web/wwwroot/bench-template.html b/src/NetproxySolution.Web/wwwroot/bench-template.html
new file mode 100644
index 0000000..c20c5a0
--- /dev/null
+++ b/src/NetproxySolution.Web/wwwroot/bench-template.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title></title>
+</head>
+<body>
+
+ <template id="myTemplate" type="text/template">
+ </template>
+
+ <div id="output"></div>
+
+ <script src="template.js"></script>
+
+ <script>
+ async function getTemplate(url)
+ {
+ try
+ {
+ const response = await fetch(url);
+ if (!response.ok) throw new Error('Network response was not ok');
+ const text = await response.text();
+ return text;
+ }
+ catch (error)
+ {
+ console.error('Fetch error:', error);
+ return null;
+ }
+ }
+
+
+ (async () =>
+ {
+ function currentYear()
+ {
+ return new Date().getFullYear();
+ }
+
+ const data = {
+ "title": "My Blog",
+ "menu": [
+ { "name": "Home", "url": "/" },
+ { "name": "About", "url": "/about" },
+ { "name": "Contact", "url": "/contact" }
+ ],
+ "sectionTitle": "Latest Articles",
+ "articles": [
+ { "title": "Article 1", "content": "Content of article 1." },
+ { "title": "Article 2", "content": "Content of article 2." }
+ ],
+ "aboutMe": "This is a short bio about me.",
+ "links": [
+ { "name": "GitHub", "url": "https://github.com" },
+ { "name": "Twitter", "url": "https://twitter.com" }
+ ],
+ "currentYear": currentYear
+ }
+
+ const template = document.getElementById('myTemplate');
+
+ template.textContent = await getTemplate('template-test.html');
+
+ const myHtml = TemplateHtml(template, data)
+
+ document.getElementById('output').innerHTML = myHtml;
+
+ const start = performance.now();
+ for (let i = 0; i < 1000; i++)
+ {
+ const html = TemplateHtml(template, data)
+ }
+ const end = performance.now();
+ console.log(`Rendering took ${end - start} ms`);
+
+ })();
+ </script>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/src/NetproxySolution.Web/wwwroot/template-fp.js b/src/NetproxySolution.Web/wwwroot/template-fp.js
new file mode 100644
index 0000000..3a750eb
--- /dev/null
+++ b/src/NetproxySolution.Web/wwwroot/template-fp.js
@@ -0,0 +1,134 @@
+function XSS(unsafe)
+{
+ if (Array.isArray(unsafe))
+ {
+ return unsafe.map(item => XSS(item)).join(', ');
+ }
+ if (unsafe === null || unsafe === undefined)
+ {
+ return '';
+ }
+ return String(unsafe).replace(/[&<>"']/g, match =>
+ ({
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": '''
+ }[match]));
+}
+
+// Template functionality
+Element.prototype.Template = function (template, data, append)
+{
+ var strHtml = window.TemplateHtml(template, data);
+ if (append)
+ {
+ var temp = document.createElement("span");
+ temp.innerHTML = strHtml;
+ this.insertAdjacentElement('beforeend', temp);
+ }
+ else
+ {
+ this.innerHTML = strHtml;
+ }
+};
+
+function TemplateHtml(template, data)
+{
+ try
+ {
+ var element = typeof template === "string" ? document.getElementById(template) : template;
+ if (!element)
+ throw new Error("Template not found.");
+ if (!element.jscache)
+ {
+ var html = element.textContent.replace(/\s+/g, ' ').trim();
+ var jsParts = ["let _='';"];
+ var concatParts = [];
+ var index = 0;
+ while (index < html.length)
+ {
+ var start = html.indexOf('<%', index);
+ if (start < 0)
+ {
+ concatParts.push("'" + html.slice(index).replace(/'/g, "\\'") + "'");
+ if (concatParts.length > 0)
+ {
+ jsParts.push("_+=" + concatParts.join('+') + ";");
+ concatParts = [];
+ }
+ break;
+ }
+ if (start > index)
+ {
+ concatParts.push("'" + html.slice(index, start).replace(/'/g, "\\'") + "'");
+ }
+ index = start + 2;
+ var is_ = html[index] === '=';
+ if (is_)
+ index++;
+ var end = html.indexOf('%>', index);
+ if (end < 0)
+ throw new Error("Unclosed template tag.");
+ var code = html.slice(index, end).trim();
+ if (is_)
+ {
+ concatParts.push("XSS(" + code + ")");
+ }
+ else
+ {
+ if (concatParts.length > 0)
+ {
+ jsParts.push("_+=" + concatParts.join('+') + ";");
+ concatParts = [];
+ }
+ jsParts.push(code + ";");
+ }
+ index = end + 2;
+ }
+ if (concatParts.length > 0)
+ {
+ jsParts.push("_+=" + concatParts.join('+') + ";");
+ concatParts = [];
+ }
+ jsParts.push('return _;');
+ var js = jsParts.join('');
+ jsParts = [];
+ element.jscache = function (data)
+ {
+ var context = { data, XSS };
+ for (var key in data)
+ {
+ if (typeof data[key] === 'function')
+ {
+ try
+ {
+ context.data[key] = data[key]();
+ }
+ catch (err)
+ {
+ console.error(`Error executing function ${key}: ${err.message}`);
+ context.data[key] = '';
+ }
+ }
+ }
+ try
+ {
+ return (function (ctx) { with (ctx) { return eval('(function() {' + js + '})()'); } })(context);
+ }
+ catch (err)
+ {
+ console.error(`Template execution error: ${err.message}`);
+ return '';
+ }
+ };
+ }
+ return element.jscache(data);
+ }
+ catch (err)
+ {
+ console.error("Template error:", err.message);
+ return "";
+ }
+}
\ No newline at end of file
diff --git a/src/NetproxySolution.Web/wwwroot/template-test.html b/src/NetproxySolution.Web/wwwroot/template-test.html
new file mode 100644
index 0000000..cb0ffa5
--- /dev/null
+++ b/src/NetproxySolution.Web/wwwroot/template-test.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>{{ title }}</title>
+</head>
+<body>
+ <header>
+ <h1><%= data.title %></h1>
+ </header>
+
+ <nav>
+ <ul>
+ <% data.menu.forEach(function(item) { %>
+ <li><a href="<%= item.url %>"><%= item.name %></a></li>
+ <% }); %>
+ </ul>
+ </nav>
+
+ <main>
+ <section>
+ <h2><%= data.sectionTitle %></h2>
+ <% if (data.articles.length) { %>
+ <% data.articles.forEach(function(article) { %>
+ <article>
+ <h3><%= article.title %></h3>
+ <p><%= article.content %></p>
+ </article>
+ <% }); %>
+ <% } else { %>
+ <p>No articles available.</p>
+ <% } %>
+ </section>
+
+ <aside>
+ </aside>
+ </main>
+
+ <footer>
+ <p>© <%= data.currentYear %> My Website</p>
+ </footer>
+
+ </body>
+</html>
\ No newline at end of file