Add initial nest version, add tests

This commit is contained in:
2024-11-16 09:50:24 +05:30
parent 0152ebeb91
commit 5b1368dca0
45 changed files with 1247 additions and 173 deletions
+15
View File
@@ -0,0 +1,15 @@
package tests
import (
"git.virtual.blue/tomgracey/template-nest-go"
"testing"
)
func TestInitialize(t *testing.T) {
_, err := templatenest.New(templatenest.Option{
TemplateDir: "templates",
})
if err != nil {
t.Fatalf("Failed to initialize TemplateNest: %+v", err)
}
}
+145
View File
@@ -0,0 +1,145 @@
package tests
import (
"git.virtual.blue/tomgracey/template-nest-go"
"github.com/stretchr/testify/assert"
"testing"
)
func TestRenderSimplePage(t *testing.T) {
nest, err := templatenest.New(templatenest.Option{
TemplateDir: "templates",
})
if err != nil {
t.Fatalf("Failed to initialize TemplateNest: %+v", err)
}
page := templatenest.Hash{
"TEMPLATE": "00-simple-page",
"variable": "Simple Variable",
"simple_component": []templatenest.Hash{
templatenest.Hash{
"TEMPLATE": "01-simple-component",
"variable": "Simple Variable in Simple Component",
},
},
}
outputPage := templatenest.Hash{"TEMPLATE": "output/01-simple-page"}
render, err := nest.Render(page)
if err != nil {
t.Fatalf("Render failed for page: %+v", err)
}
outputRender := nest.MustRender(outputPage)
assert.Equal(t, outputRender, render, "Rendered output does not match expected output")
}
func TestRenderIncompletePage(t *testing.T) {
nest, err := templatenest.New(templatenest.Option{TemplateDir: "templates"})
if err != nil {
t.Fatalf("Failed to initialize TemplateNest: %+v", err)
}
page := templatenest.Hash{
"TEMPLATE": "00-simple-page",
"variable": "Simple Variable",
"simple_component": []templatenest.Hash{
templatenest.Hash{
"TEMPLATE": "01-simple-component",
},
},
}
outputPage := templatenest.Hash{"TEMPLATE": "output/03-incomplete-page"}
render := nest.MustRender(page)
outputRender := nest.MustRender(outputPage)
assert.Equal(t, outputRender, render, "Rendered output does not match expected output")
}
func TestRenderComplexPage(t *testing.T) {
nest, err := templatenest.New(templatenest.Option{TemplateDir: "templates"})
if err != nil {
t.Fatalf("Failed to initialize TemplateNest: %+v", err)
}
page := templatenest.Hash{
"TEMPLATE": "10-complex-page",
"title": "Complex Page",
"pre_body": templatenest.Hash{
"TEMPLATE": "18-styles",
},
"navigation": templatenest.Hash{
"TEMPLATE": "11-navigation",
"banner": templatenest.Hash{
"TEMPLATE": "12-navigation-banner",
},
"items": []templatenest.Hash{
templatenest.Hash{"TEMPLATE": "13-navigation-item-00-services"},
templatenest.Hash{"TEMPLATE": "13-navigation-item-01-resources"},
},
},
"hero_section": templatenest.Hash{
"TEMPLATE": "14-hero-section",
},
"main_content": []templatenest.Hash{
templatenest.Hash{"TEMPLATE": "15-isdc-card"},
templatenest.Hash{
"TEMPLATE": "16-vb-brand-cards",
"cards": []templatenest.Hash{
templatenest.Hash{
"TEMPLATE": "17-vb-brand-card-00",
"parent_classes": "p-card brand-card col-4",
},
templatenest.Hash{
"TEMPLATE": "17-vb-brand-card-01",
"parent_classes": "p-card brand-card col-4",
},
templatenest.Hash{
"TEMPLATE": "17-vb-brand-card-02",
"parent_classes": "p-card brand-card col-4",
},
},
},
},
"post_footer": templatenest.Hash{
"TEMPLATE": "19-scripts",
},
}
outputPage := templatenest.Hash{"TEMPLATE": "output/02-complex-page"}
render := nest.MustRender(page)
outputRender := nest.MustRender(outputPage)
assert.Equal(t, outputRender, render, "Rendered output does not match expected output")
}
func TestRenderArrayOfTemplateHash(t *testing.T) {
nest, err := templatenest.New(templatenest.Option{TemplateDir: "templates"})
if err != nil {
t.Fatalf("Failed to initialize TemplateNest: %+v", err)
}
page := []templatenest.Hash{
templatenest.Hash{
"TEMPLATE": "01-simple-component",
"variable": "This is a variable",
},
templatenest.Hash{
"TEMPLATE": "01-simple-component",
"variable": "This is another variable",
},
}
outputPage := templatenest.Hash{"TEMPLATE": "output/13-render-with-array-of-template-hash"}
render := nest.MustRender(page)
outputRender := nest.MustRender(outputPage)
assert.Equal(t, outputRender, render, "Rendered output does not match expected output")
}
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple Page</title>
</head>
<body>
<p>A fairly simple page to test the performance of Template::Nest.</p>
<p><% variable %></p>
<% simple_component %>
</body>
</html>
+13
View File
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple Page</title>
</head>
<body>
<p>A fairly simple page to test the performance of Template::Nest.</p>
<p><!--% variable %--></p>
<!--% simple_component %-->
</body>
</html>
@@ -0,0 +1 @@
<p><% variable %></p>
@@ -0,0 +1 @@
<p>\<!--% variable %--></p>
+1
View File
@@ -0,0 +1 @@
<p><!--% variable %--></p>
@@ -0,0 +1,7 @@
<p>
This is a simple component on multiple lines.
</p>
<p>
This is used for fixed-indent testing.
</p>
@@ -0,0 +1,7 @@
<p>
This is a simple component on multiple lines.
</p>
<p>
This is used for fixed-indent testing.
</p>
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple Page</title>
</head>
<body>
<p>A fairly simple page to test the performance of Template::Nest.</p>
<p><!--% space.inside %--></p>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
<!--% variable %-->
+29
View File
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><!--% title %--></title>
<link rel="stylesheet" href="/03-resources/style.css" />
<!--% pre_body %-->
</head>
<body>
<header id="navigation" class="p-navigation is-dark">
<!--% navigation %-->
</header>
<section class="p-strip--light is-bordered hero-section">
<!--% hero_section %-->
</section>
<main class="row">
<!--% main_content %-->
</main>
<footer>
<h2>virtual.blue</h2>
</footer>
<!--% post_footer %-->
</body>
</html>
+20
View File
@@ -0,0 +1,20 @@
<div class="p-navigation__row">
<!--% banner %-->
<nav class="p-navigation__nav" aria-label="Example sub navigation">
<ul class="p-navigation__items">
<!--% items %-->
</ul>
<ul class="p-navigation__items">
<li class="p-navigation__item--dropdown-toggle" id="link-4">
<a class="p-navigation__link" aria-controls="account-menu">
My account
</a>
<ul class="p-navigation__dropdown--right" id="account-menu" aria-hidden="true">
<li>
<a href="#" class="p-navigation__dropdown-item">Sign out</a>
</li>
</ul>
</li>
</ul>
</nav>
</div>
+11
View File
@@ -0,0 +1,11 @@
<div class="p-navigation__banner">
<div class="p-navigation__tagged-logo">
<a class="p-navigation__link" href="#">
<span class="p-navigation__logo-title">
<img class="nav-vb-logo" src="https://virtual.blue/resources/img/vb-small-dark-bg.png" alt="virtual.blue logo">
</span>
</a>
</div>
<a href="#navigation" class="p-navigation__toggle--open" title="menu">Menu</a>
<a href="#navigation-closed" class="p-navigation__toggle--close" title="close menu">Close menu</a>
</div>
@@ -0,0 +1,17 @@
<li class="p-navigation__item--dropdown-toggle" id="link-2">
<a href="#link-2-menu" aria-controls="link-2-menu" class="p-navigation__link">Services</a>
<ul class="p-navigation__dropdown" id="link-2-menu" aria-hidden="true">
<li>
<a href="#" class="p-navigation__dropdown-item">Web & Mobile Apps</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Legacy Code</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Migrations</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Replacement Systems</a>
</li>
</ul>
</li>
@@ -0,0 +1,14 @@
<li class="p-navigation__item--dropdown-toggle" id="link-3">
<a href="#link-3-menu" aria-controls="link-3-menu" class="p-navigation__link">Resources</a>
<ul class="p-navigation__dropdown" id="link-3-menu" aria-hidden="true">
<li>
<a href="#" class="p-navigation__dropdown-item">Point Drag Controls</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Delay Proxy</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">TaskPipe</a>
</li>
</ul>
</li>
+4
View File
@@ -0,0 +1,4 @@
<div class="row">
<h1>Software Systems</h1>
<p>Quality web and app specialists at low cost. New app development. Web-scrapers and crawlers. Full systems. Legacy repairs.</p>
</div>
+14
View File
@@ -0,0 +1,14 @@
<div class="p-card">
<div class="row">
<div class="col-4">
<img src="https://virtual.blue/resources/img/isdc-zoom.png">
</div>
<div class="col-8">
<h3>Raku Prodigy ISDC</h3>
<p class="p-card__content">
Are you a rising coding talent with a flair for innovative system development?
Make a name for yourself by winning our <a href="https://virtual.blue/isdc">web development competition</a>.
</p>
</div>
</div>
</div>
+3
View File
@@ -0,0 +1,3 @@
<div class="row brand-cards-wrapper">
<!--% cards %-->
</div>
+9
View File
@@ -0,0 +1,9 @@
<div class="<!--% parent_classes %-->">
<div class="p-card__content">
<img class="p-card__image" alt="" src="https://virtual.blue/resources/img/home/Cost%20Minimising.svg">
<h4>
Cost Minimising
</h4>
<p class="u-no-padding--bottom">Through our efficient approach to project management we are able to offer some of the lowest service rates in the industry - without compromising on quality.</p>
</div>
</div>
+9
View File
@@ -0,0 +1,9 @@
<div class="<!--% parent_classes %-->">
<div class="p-card__content">
<img class="p-card__image" alt="" src="https://virtual.blue/resources/img/home/Code%20Warranty.svg">
<h4>
Code Warranty
</h4>
<p class="u-no-padding--bottom">As standard we continue to provide support for 6 months after you have accepted the code. This includes explaining usage, performing minor adjustments and ironing out any bugs. Subject to contract terms.</p>
</div>
</div>
+9
View File
@@ -0,0 +1,9 @@
<div class="<!--% parent_classes %-->">
<div class="p-card__content">
<img class="p-card__image" alt="" src="https://virtual.blue/resources/img/home/Tailor%20Made%20Solutions.svg">
<h4>
Tailor Made Solutions
</h4>
<p class="u-no-padding--bottom">When evaluating your case we'll consider your individual requirements, your specific business needs and the particular problem you are facing - so we'll always propose solutions which are uniquely tailored to your situation.</p>
</div>
</div>
+20
View File
@@ -0,0 +1,20 @@
<style>
.nav-vb-logo {
max-width: 200px;
}
.hero-section {
background-image: url('/03-resources/bg-header.jpg');
background-size: cover;
}
main {
margin-top: 1em;
}
main .brand-card img {
max-width: 50%;
margin: auto;
}
footer {
text-align: center;
padding: 4em;
}
</style>
+49
View File
@@ -0,0 +1,49 @@
<script>
function toggleDropdown(toggle, open) {
let parentElement = toggle.parentNode;
let dropdown = document.getElementById(toggle.getAttribute('aria-controls'));
dropdown.setAttribute('aria-hidden', !open);
if (open) {
parentElement.classList.add('is-active');
} else {
parentElement.classList.remove('is-active');
}
}
function closeAllDropdowns(toggles) {
toggles.forEach(function (toggle) {
toggleDropdown(toggle, false);
});
}
function handleClickOutside(toggles, containerClass) {
document.addEventListener('click', function (event) {
let target = event.target;
if (target.closest) {
if (!target.closest(containerClass)) {
closeAllDropdowns(toggles);
}
}
});
}
function initNavDropdowns(containerClass) {
let toggles = [].slice.call(document.querySelectorAll(containerClass + ' [aria-controls]'));
handleClickOutside(toggles, containerClass);
toggles.forEach(function (toggle) {
toggle.addEventListener('click', function (e) {
e.preventDefault();
const shouldOpen = !toggle.parentNode.classList.contains('is-active');
closeAllDropdowns(toggles);
toggleDropdown(toggle, shouldOpen);
});
});
}
initNavDropdowns('.p-navigation__item--dropdown-toggle');
</script>
+3
View File
@@ -0,0 +1,3 @@
const tmp = () => {
/* <!--% var %--> */
};
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple Page</title>
</head>
<body>
<p>A fairly simple page to test the performance of Template::Nest.</p>
<p>Simple Variable</p>
<p>Simple Variable in Simple Component</p>
</body>
</html>
+196
View File
@@ -0,0 +1,196 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Complex Page</title>
<link rel="stylesheet" href="/03-resources/style.css" />
<style>
.nav-vb-logo {
max-width: 200px;
}
.hero-section {
background-image: url('/03-resources/bg-header.jpg');
background-size: cover;
}
main {
margin-top: 1em;
}
main .brand-card img {
max-width: 50%;
margin: auto;
}
footer {
text-align: center;
padding: 4em;
}
</style>
</head>
<body>
<header id="navigation" class="p-navigation is-dark">
<div class="p-navigation__row">
<div class="p-navigation__banner">
<div class="p-navigation__tagged-logo">
<a class="p-navigation__link" href="#">
<span class="p-navigation__logo-title">
<img class="nav-vb-logo" src="https://virtual.blue/resources/img/vb-small-dark-bg.png" alt="virtual.blue logo">
</span>
</a>
</div>
<a href="#navigation" class="p-navigation__toggle--open" title="menu">Menu</a>
<a href="#navigation-closed" class="p-navigation__toggle--close" title="close menu">Close menu</a>
</div>
<nav class="p-navigation__nav" aria-label="Example sub navigation">
<ul class="p-navigation__items">
<li class="p-navigation__item--dropdown-toggle" id="link-2">
<a href="#link-2-menu" aria-controls="link-2-menu" class="p-navigation__link">Services</a>
<ul class="p-navigation__dropdown" id="link-2-menu" aria-hidden="true">
<li>
<a href="#" class="p-navigation__dropdown-item">Web & Mobile Apps</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Legacy Code</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Migrations</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Replacement Systems</a>
</li>
</ul>
</li><li class="p-navigation__item--dropdown-toggle" id="link-3">
<a href="#link-3-menu" aria-controls="link-3-menu" class="p-navigation__link">Resources</a>
<ul class="p-navigation__dropdown" id="link-3-menu" aria-hidden="true">
<li>
<a href="#" class="p-navigation__dropdown-item">Point Drag Controls</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Delay Proxy</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">TaskPipe</a>
</li>
</ul>
</li>
</ul>
<ul class="p-navigation__items">
<li class="p-navigation__item--dropdown-toggle" id="link-4">
<a class="p-navigation__link" aria-controls="account-menu">
My account
</a>
<ul class="p-navigation__dropdown--right" id="account-menu" aria-hidden="true">
<li>
<a href="#" class="p-navigation__dropdown-item">Sign out</a>
</li>
</ul>
</li>
</ul>
</nav>
</div>
</header>
<section class="p-strip--light is-bordered hero-section">
<div class="row">
<h1>Software Systems</h1>
<p>Quality web and app specialists at low cost. New app development. Web-scrapers and crawlers. Full systems. Legacy repairs.</p>
</div>
</section>
<main class="row">
<div class="p-card">
<div class="row">
<div class="col-4">
<img src="https://virtual.blue/resources/img/isdc-zoom.png">
</div>
<div class="col-8">
<h3>Raku Prodigy ISDC</h3>
<p class="p-card__content">
Are you a rising coding talent with a flair for innovative system development?
Make a name for yourself by winning our <a href="https://virtual.blue/isdc">web development competition</a>.
</p>
</div>
</div>
</div><div class="row brand-cards-wrapper">
<div class="p-card brand-card col-4">
<div class="p-card__content">
<img class="p-card__image" alt="" src="https://virtual.blue/resources/img/home/Cost%20Minimising.svg">
<h4>
Cost Minimising
</h4>
<p class="u-no-padding--bottom">Through our efficient approach to project management we are able to offer some of the lowest service rates in the industry - without compromising on quality.</p>
</div>
</div><div class="p-card brand-card col-4">
<div class="p-card__content">
<img class="p-card__image" alt="" src="https://virtual.blue/resources/img/home/Code%20Warranty.svg">
<h4>
Code Warranty
</h4>
<p class="u-no-padding--bottom">As standard we continue to provide support for 6 months after you have accepted the code. This includes explaining usage, performing minor adjustments and ironing out any bugs. Subject to contract terms.</p>
</div>
</div><div class="p-card brand-card col-4">
<div class="p-card__content">
<img class="p-card__image" alt="" src="https://virtual.blue/resources/img/home/Tailor%20Made%20Solutions.svg">
<h4>
Tailor Made Solutions
</h4>
<p class="u-no-padding--bottom">When evaluating your case we'll consider your individual requirements, your specific business needs and the particular problem you are facing - so we'll always propose solutions which are uniquely tailored to your situation.</p>
</div>
</div>
</div>
</main>
<footer>
<h2>virtual.blue</h2>
</footer>
<script>
function toggleDropdown(toggle, open) {
let parentElement = toggle.parentNode;
let dropdown = document.getElementById(toggle.getAttribute('aria-controls'));
dropdown.setAttribute('aria-hidden', !open);
if (open) {
parentElement.classList.add('is-active');
} else {
parentElement.classList.remove('is-active');
}
}
function closeAllDropdowns(toggles) {
toggles.forEach(function (toggle) {
toggleDropdown(toggle, false);
});
}
function handleClickOutside(toggles, containerClass) {
document.addEventListener('click', function (event) {
let target = event.target;
if (target.closest) {
if (!target.closest(containerClass)) {
closeAllDropdowns(toggles);
}
}
});
}
function initNavDropdowns(containerClass) {
let toggles = [].slice.call(document.querySelectorAll(containerClass + ' [aria-controls]'));
handleClickOutside(toggles, containerClass);
toggles.forEach(function (toggle) {
toggle.addEventListener('click', function (e) {
e.preventDefault();
const shouldOpen = !toggle.parentNode.classList.contains('is-active');
closeAllDropdowns(toggles);
toggleDropdown(toggle, shouldOpen);
});
});
}
initNavDropdowns('.p-navigation__item--dropdown-toggle');
</script>
</body>
</html>
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple Page</title>
</head>
<body>
<p>A fairly simple page to test the performance of Template::Nest.</p>
<p>Simple Variable</p>
<p></p>
</body>
</html>
@@ -0,0 +1,17 @@
<!-- BEGIN 00-simple-page -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple Page</title>
</head>
<body>
<p>A fairly simple page to test the performance of Template::Nest.</p>
<p>Simple Variable</p>
<!-- BEGIN 01-simple-component -->
<p>Simple Variable in Simple Component</p>
<!-- END 01-simple-component -->
</body>
</html>
<!-- END 00-simple-page -->
@@ -0,0 +1,17 @@
<!--! BEGIN 00-simple-page !-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple Page</title>
</head>
<body>
<p>A fairly simple page to test the performance of Template::Nest.</p>
<p>Simple Variable</p>
<!--! BEGIN 01-simple-component !-->
<p>Simple Variable in Simple Component</p>
<!--! END 01-simple-component !-->
</body>
</html>
<!--! END 00-simple-page !-->
@@ -0,0 +1,3 @@
const tmp = () => {
/* Simple Variable */
};
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple Page</title>
</head>
<body>
<p>A fairly simple page to test the performance of Template::Nest.</p>
<p>Simple Variable</p>
<p>
This is a simple component on multiple lines.
</p>
<p>
This is used for fixed-indent testing.
</p>
</body>
</html>
@@ -0,0 +1,196 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Complex Page</title>
<link rel="stylesheet" href="/03-resources/style.css" />
<style>
.nav-vb-logo {
max-width: 200px;
}
.hero-section {
background-image: url('/03-resources/bg-header.jpg');
background-size: cover;
}
main {
margin-top: 1em;
}
main .brand-card img {
max-width: 50%;
margin: auto;
}
footer {
text-align: center;
padding: 4em;
}
</style>
</head>
<body>
<header id="navigation" class="p-navigation is-dark">
<div class="p-navigation__row">
<div class="p-navigation__banner">
<div class="p-navigation__tagged-logo">
<a class="p-navigation__link" href="#">
<span class="p-navigation__logo-title">
<img class="nav-vb-logo" src="https://virtual.blue/resources/img/vb-small-dark-bg.png" alt="virtual.blue logo">
</span>
</a>
</div>
<a href="#navigation" class="p-navigation__toggle--open" title="menu">Menu</a>
<a href="#navigation-closed" class="p-navigation__toggle--close" title="close menu">Close menu</a>
</div>
<nav class="p-navigation__nav" aria-label="Example sub navigation">
<ul class="p-navigation__items">
<li class="p-navigation__item--dropdown-toggle" id="link-2">
<a href="#link-2-menu" aria-controls="link-2-menu" class="p-navigation__link">Services</a>
<ul class="p-navigation__dropdown" id="link-2-menu" aria-hidden="true">
<li>
<a href="#" class="p-navigation__dropdown-item">Web & Mobile Apps</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Legacy Code</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Migrations</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Replacement Systems</a>
</li>
</ul>
</li><li class="p-navigation__item--dropdown-toggle" id="link-3">
<a href="#link-3-menu" aria-controls="link-3-menu" class="p-navigation__link">Resources</a>
<ul class="p-navigation__dropdown" id="link-3-menu" aria-hidden="true">
<li>
<a href="#" class="p-navigation__dropdown-item">Point Drag Controls</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">Delay Proxy</a>
</li>
<li>
<a href="#" class="p-navigation__dropdown-item">TaskPipe</a>
</li>
</ul>
</li>
</ul>
<ul class="p-navigation__items">
<li class="p-navigation__item--dropdown-toggle" id="link-4">
<a class="p-navigation__link" aria-controls="account-menu">
My account
</a>
<ul class="p-navigation__dropdown--right" id="account-menu" aria-hidden="true">
<li>
<a href="#" class="p-navigation__dropdown-item">Sign out</a>
</li>
</ul>
</li>
</ul>
</nav>
</div>
</header>
<section class="p-strip--light is-bordered hero-section">
<div class="row">
<h1>Software Systems</h1>
<p>Quality web and app specialists at low cost. New app development. Web-scrapers and crawlers. Full systems. Legacy repairs.</p>
</div>
</section>
<main class="row">
<div class="p-card">
<div class="row">
<div class="col-4">
<img src="https://virtual.blue/resources/img/isdc-zoom.png">
</div>
<div class="col-8">
<h3>Raku Prodigy ISDC</h3>
<p class="p-card__content">
Are you a rising coding talent with a flair for innovative system development?
Make a name for yourself by winning our <a href="https://virtual.blue/isdc">web development competition</a>.
</p>
</div>
</div>
</div><div class="row brand-cards-wrapper">
<div class="p-card brand-card col-4">
<div class="p-card__content">
<img class="p-card__image" alt="" src="https://virtual.blue/resources/img/home/Cost%20Minimising.svg">
<h4>
Cost Minimising
</h4>
<p class="u-no-padding--bottom">Through our efficient approach to project management we are able to offer some of the lowest service rates in the industry - without compromising on quality.</p>
</div>
</div><div class="p-card brand-card col-4">
<div class="p-card__content">
<img class="p-card__image" alt="" src="https://virtual.blue/resources/img/home/Code%20Warranty.svg">
<h4>
Code Warranty
</h4>
<p class="u-no-padding--bottom">As standard we continue to provide support for 6 months after you have accepted the code. This includes explaining usage, performing minor adjustments and ironing out any bugs. Subject to contract terms.</p>
</div>
</div><div class="p-card brand-card col-4">
<div class="p-card__content">
<img class="p-card__image" alt="" src="https://virtual.blue/resources/img/home/Tailor%20Made%20Solutions.svg">
<h4>
Tailor Made Solutions
</h4>
<p class="u-no-padding--bottom">When evaluating your case we'll consider your individual requirements, your specific business needs and the particular problem you are facing - so we'll always propose solutions which are uniquely tailored to your situation.</p>
</div>
</div>
</div>
</main>
<footer>
<h2>virtual.blue</h2>
</footer>
<script>
function toggleDropdown(toggle, open) {
let parentElement = toggle.parentNode;
let dropdown = document.getElementById(toggle.getAttribute('aria-controls'));
dropdown.setAttribute('aria-hidden', !open);
if (open) {
parentElement.classList.add('is-active');
} else {
parentElement.classList.remove('is-active');
}
}
function closeAllDropdowns(toggles) {
toggles.forEach(function (toggle) {
toggleDropdown(toggle, false);
});
}
function handleClickOutside(toggles, containerClass) {
document.addEventListener('click', function (event) {
let target = event.target;
if (target.closest) {
if (!target.closest(containerClass)) {
closeAllDropdowns(toggles);
}
}
});
}
function initNavDropdowns(containerClass) {
let toggles = [].slice.call(document.querySelectorAll(containerClass + ' [aria-controls]'));
handleClickOutside(toggles, containerClass);
toggles.forEach(function (toggle) {
toggle.addEventListener('click', function (e) {
e.preventDefault();
const shouldOpen = !toggle.parentNode.classList.contains('is-active');
closeAllDropdowns(toggles);
toggleDropdown(toggle, shouldOpen);
});
});
}
initNavDropdowns('.p-navigation__item--dropdown-toggle');
</script>
</body>
</html>
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple Page</title>
</head>
<body>
<p>A fairly simple page to test the performance of Template::Nest.</p>
<p>Simple Variable</p>
<p><!--% variable %--></p>
</body>
</html>
@@ -0,0 +1 @@
Simple Variable
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple Page</title>
</head>
<body>
<p>A fairly simple page to test the performance of Template::Nest.</p>
<p>A variable inside a space.</p>
</body>
</html>
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple Page</title>
</head>
<body>
<p>A fairly simple page to test the performance of Template::Nest.</p>
<p>Simple Variable</p>
<p>Simple Variable in Simple Component</p><strong>Another test</strong><p>Simple Variable in Simple Component</p><strong>Another nested test 2</strong>
</body>
</html>
@@ -0,0 +1 @@
<p>This is a variable</p><p>This is another variable</p>