attempt at speeding up images

This commit is contained in:
Spencer Flagg 2023-05-01 13:58:46 +02:00
parent f3774f11f4
commit f1a61dd8bc
37 changed files with 3351 additions and 3848 deletions

View file

@ -1,3 +1,10 @@
const UpgradeHelper = require('@11ty/eleventy-upgrade-help');
//const pluginImages = require("./eleventy.config.images.js");
const { eleventyImagePlugin } = require('@11ty/eleventy-img');
const eleventyWebcPlugin = require('@11ty/eleventy-plugin-webc');
const htmlmin = require('html-minifier'); const htmlmin = require('html-minifier');
const dateFns = require('date-fns'); const dateFns = require('date-fns');
//const lazyImagesPlugin = require('eleventy-plugin-lazyimages'); //const lazyImagesPlugin = require('eleventy-plugin-lazyimages');
@ -8,13 +15,42 @@ const translations = require('./src/_data/i18n');
const markdownIt = require('markdown-it'); const markdownIt = require('markdown-it');
const markdownItVideo = require('markdown-it-video'); const markdownItVideo = require('markdown-it-video');
// https://github.com/saneef/eleventy-plugin-img2picture
//const img2picture = require("eleventy-plugin-img2picture");
module.exports = function (eleventyConfig) { module.exports = function (eleventyConfig) {
// WebC
eleventyConfig.addPlugin(eleventyWebcPlugin, {
components: [
// …
// Add as a global WebC component
'npm:@11ty/eleventy-img/*.webc',
],
});
// Image plugin
eleventyConfig.addPlugin(eleventyImagePlugin, {
// Set global default options
formats: ['webp', 'jpeg'],
urlPath: '/img/',
// Notably `outputDir` is resolved automatically
// to the project output directory
defaultAttributes: {
loading: 'lazy',
decoding: 'async',
},
});
let markdownLibrary = markdownIt().use(markdownItVideo); let markdownLibrary = markdownIt().use(markdownItVideo);
eleventyConfig.setLibrary('md', markdownLibrary); eleventyConfig.setLibrary('md', markdownLibrary);
// PLUGINS ************************************************************** // PLUGINS **************************************************************
//eleventyConfig.addPlugin(pluginImages);
eleventyConfig.addPlugin(syntaxHighlight); eleventyConfig.addPlugin(syntaxHighlight);
// does not work with background images // does not work with background images
@ -36,6 +72,9 @@ module.exports = function (eleventyConfig) {
}, },
}); });
// If you have other `addPlugin` calls, its important that UpgradeHelper is added last.
eleventyConfig.addPlugin(UpgradeHelper);
eleventyConfig.setEjsOptions({ eleventyConfig.setEjsOptions({
rmWhitespace: true, rmWhitespace: true,
context: { context: {

34
eleventy.config.images.js Normal file
View file

@ -0,0 +1,34 @@
const path = require('path');
const eleventyImage = require('@11ty/eleventy-img');
module.exports = (eleventyConfig) => {
function relativeToInputPath(inputPath, relativeFilePath) {
const split = inputPath.split('/');
split.pop();
return path.resolve(split.join(path.sep), relativeFilePath);
}
// Eleventy Image shortcode
// https://www.11ty.dev/docs/plugins/image/
eleventyConfig.addAsyncShortcode('image', async function imageShortcode(src, alt, widths, sizes) {
// Full list of formats here: https://www.11ty.dev/docs/plugins/image/#output-formats
// Warning: Avif can be resource-intensive so take care!
const formats = ['avif', 'webp', 'auto'];
const file = relativeToInputPath(this.page.inputPath, src);
const metadata = await eleventyImage(file, {
widths: widths || ['auto'],
formats,
outputDir: path.join(eleventyConfig.dir.output, 'img'), // Advanced usage note: `eleventyConfig.dir` works here because were using addPlugin.
});
// TODO loading=eager and fetchpriority=high
const imageAttributes = {
alt,
sizes,
loading: 'lazy',
decoding: 'async',
};
return eleventyImage.generateHTML(metadata, imageAttributes);
});
};

5776
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -21,8 +21,9 @@
}, },
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@11ty/eleventy": "^0.12.1", "@11ty/eleventy": "^2.0.1",
"@11ty/eleventy-plugin-syntaxhighlight": "^3.1.1", "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.1",
"@11ty/eleventy-plugin-webc": "^0.11.0",
"autoprefixer": "^10.2.6", "autoprefixer": "^10.2.6",
"copy-webpack-plugin": "^9.0.0", "copy-webpack-plugin": "^9.0.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
@ -68,6 +69,8 @@
] ]
}, },
"dependencies": { "dependencies": {
"@11ty/eleventy-img": "^3.1.0",
"@11ty/eleventy-upgrade-help": "^2.0.5",
"@glidejs/glide": "^3.4.1", "@glidejs/glide": "^3.4.1",
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"eleventy-plugin-i18n": "^0.1.3", "eleventy-plugin-i18n": "^0.1.3",

View file

@ -0,0 +1,43 @@
<article class="blurb__wrapper">
<section>
<p>
<em>Complete</em> and <em>easy-to-use</em> virtual guide for learning, understanding, and visualizing the complexities of human anatomy in 3D.
Includes information and images for each anatomical system and part, multiple options to interact with the <em>3D anatomy</em> models (hiding, fading, etc), and much more.
</p>
<p class="hide-on-mobile">
The <%= site.site_name %> app can be downloaded and tested for free, which contains the skeleton and ligaments, other anatomical systems can be purchased separately.
The anatomy app is available on <em>most platforms</em> (android, iOS, windows and mac) and can be used on your phone, tablet or desktop pc.
</p>
</section>
<section>
<div class="before-and-after">
<div class='img background-img'></div>
<div class='img foreground-img'></div>
<input type="range" min="1" max="100" value="59" class="slider" name='slider' id="before-and-after__slider">
<div class='slider-button'></div>
</div>
</section>
</article>
<script>
document.querySelector('#before-and-after__slider').addEventListener('input', (e) => {
const sliderPos = e.target.value;
// Update the width of the foreground image
document.querySelector('.foreground-img').style.width = `${sliderPos}%`;
// Update the position of the slider button
document.querySelector('.slider-button').style.left = `calc(${sliderPos}% - 18px)`;
});
</script>
<style>
.before-and-after .background-img {
background-image: url('./assets/images/slider-1.png');
background-position-x: -1px;
}
.before-and-after .foreground-img {
background-image: url('./assets/images/slider-2.png');
background-position-x: -1px;
width: 59%;
}
</style>

View file

@ -20,6 +20,7 @@
<span class="alert form-alert alert--failure" id="otherError">Something went wrong. Try us on <a href="https://twitter.com/graphicvizion" target="_blank" style="font-weight: 600; color: #eee; text-decoration: underline;">Twitter</a> instead.</span> <span class="alert form-alert alert--failure" id="otherError">Something went wrong. Try us on <a href="https://twitter.com/graphicvizion" target="_blank" style="font-weight: 600; color: #eee; text-decoration: underline;">Twitter</a> instead.</span>
<span class="alert form-alert alert--success" id="success">Thanks! We'll contact you shortly.</span> <span class="alert form-alert alert--success" id="success">Thanks! We'll contact you shortly.</span>
</div> </div>
<eleventy-image src="./assets/images/contact.png" alt="photo of my tabby cat"></eleventy-image>
<img class="hide-on-mobile" src="./assets/images/contact.png" alt="contact visual anatomy 3d developers" title="contact visual anatomy 3d developers"> <img class="hide-on-mobile" src="./assets/images/contact.png" alt="contact visual anatomy 3d developers" title="contact visual anatomy 3d developers">
</section> </section>
</article> </article>

View file

@ -0,0 +1,26 @@
<article class="contact__wrapper">
<header>
<h1 id="contact">Contact Us</h1>
</header>
<section>
<div class="form">
<input type="text" placeholder="your email address goes here" id="fromEmail">
<span class="alert form-alert" id="emailError">your email address isn't valid</span>
<textarea placeholder="your message goes here" id="message">
</textarea>
<button class="btn btn--contact" type="submit" id="contactSubmit">send <svg
xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-send" width="32" height="32"
viewBox="0 0 24 24" stroke-width="2" stroke="#ffffff" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<line x1="10" y1="14" x2="21" y2="3" />
<path d="M21 3l-6.5 18a0.55 .55 0 0 1 -1 0l-3.5 -7l-7 -3.5a0.55 .55 0 0 1 0 -1l18 -6.5" />
</svg>
</button>
<span class="alert form-alert alert--failure" id="otherError">Something went wrong. Try us on <a href="https://twitter.com/graphicvizion" target="_blank" style="font-weight: 600; color: #eee; text-decoration: underline;">Twitter</a> instead.</span>
<span class="alert form-alert alert--success" id="success">Thanks! We'll contact you shortly.</span>
</div>
<eleventy-image src="./assets/images/contact.png" alt="photo of my tabby cat"></eleventy-image>
<img class="hide-on-mobile" src="./assets/images/contact.png" alt="contact visual anatomy 3d developers" title="contact visual anatomy 3d developers">
</section>
</article>

View file

@ -6,7 +6,7 @@
</header> </header>
<section class="download__content"> <section class="download__content">
<a class="platform__wrapper" href="https://apps.apple.com/il/app/visual-anatomy-3d-human/id1148048602" target="_blank"> <a class="platform__wrapper" href="https://apps.apple.com/il/app/visual-anatomy-3d-human/id1148048602" target="_blank">
<% include /store-icons/ios.svg %> <%- include('/store-icons/ios.svg') -%>
<h2> <h2>
iOS iOS
</h2> </h2>
@ -15,7 +15,7 @@
</div> </div>
</a> </a>
<a class="platform__wrapper" href="https://play.google.com/store/apps/details?id=com.graphicvizion.visualAnatomyHumanFr" target="_blank"> <a class="platform__wrapper" href="https://play.google.com/store/apps/details?id=com.graphicvizion.visualAnatomyHumanFr" target="_blank">
<% include /store-icons/android.svg %> <%- include('/store-icons/android.svg') -%>
<h2> <h2>
Android Android
</h2> </h2>
@ -24,7 +24,7 @@
</div> </div>
</a> </a>
<a class="platform__wrapper" href="https://apps.apple.com/il/app/visual-anatomy-3d-human/id1148048602" target="_blank"> <a class="platform__wrapper" href="https://apps.apple.com/il/app/visual-anatomy-3d-human/id1148048602" target="_blank">
<% include /store-icons/macos.svg %> <%- include('/store-icons/macos.svg') -%>
<h2> <h2>
macOS macOS
</h2> </h2>
@ -33,7 +33,7 @@
</div> </div>
</a> </a>
<a class="platform__wrapper" href="https://www.microsoft.com/en-us/p/visual-anatomy-human-body/9nblggh4qg21" target="_blank"> <a class="platform__wrapper" href="https://www.microsoft.com/en-us/p/visual-anatomy-human-body/9nblggh4qg21" target="_blank">
<% include /store-icons/windows.svg %> <%- include('/store-icons/windows.svg') -%>
<h2> <h2>
Windows Windows
</h2> </h2>

View file

@ -0,0 +1,45 @@
<article class="download__wrapper max-w-screen-lg">
<header>
<h1 id="download">
download now
</h1>
</header>
<section class="download__content">
<a class="platform__wrapper" href="https://apps.apple.com/il/app/visual-anatomy-3d-human/id1148048602" target="_blank">
<%- include('/store-icons/ios.svg') -%>
<h2>
iOS
</h2>
<div class="btn btn--store">
go to store
</div>
</a>
<a class="platform__wrapper" href="https://play.google.com/store/apps/details?id=com.graphicvizion.visualAnatomyHumanFr" target="_blank">
<%- include('/store-icons/android.svg') -%>
<h2>
Android
</h2>
<div class="btn btn--store">
go to store
</div>
</a>
<a class="platform__wrapper" href="https://apps.apple.com/il/app/visual-anatomy-3d-human/id1148048602" target="_blank">
<%- include('/store-icons/macos.svg') -%>
<h2>
macOS
</h2>
<div class="btn btn--store">
go to store
</div>
</a>
<a class="platform__wrapper" href="https://www.microsoft.com/en-us/p/visual-anatomy-human-body/9nblggh4qg21" target="_blank">
<%- include('/store-icons/windows.svg') -%>
<h2>
Windows
</h2>
<div class="btn btn--store">
go to store
</div>
</a>
</section>
</article>

View file

@ -0,0 +1,133 @@
<footer class="text-center">
<section>
<h3>
<a href="https://www.graphicvizion.com/" target="_blank">GraphicViZion</a>
</h3>
<div class="copywrite">
<p>© <%= new Date().getFullYear() %> by GraphicViZion</p>
<p class="build">v <%= buildInfo.version %> @ <time datetime="<%= buildInfo.time.raw %>">
<%= buildInfo.time.formatted %>
</time></p>
</div>
<div class="credit">
this site was hand-crafted by <a href="https://spencerflagg.com" target="_blank">Spencer Flagg</a>
</div>
</section>
<section>
<ul>
<li>
<a href="https://www.instagram.com/graphicvizion/" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-instagram" width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<rect x="4" y="4" width="16" height="16" rx="4" />
<circle cx="12" cy="12" r="3" />
<line x1="16.5" y1="7.5" x2="16.5" y2="7.501" />
</svg>
@graphic_vizion
</a>
</li>
<li>
<a href="https://twitter.com/graphicvizion" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-twitter"
width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none"
stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M22 4.01c-1 .49 -1.98 .689 -3 .99c-1.121 -1.265 -2.783 -1.335 -4.38 -.737s-2.643 2.06 -2.62 3.737v1c-3.245 .083 -6.135 -1.395 -8 -4c0 0 -4.182 7.433 4 11c-1.872 1.247 -3.739 2.088 -6 2c3.308 1.803 6.913 2.423 10.034 1.517c3.58 -1.04 6.522 -3.723 7.651 -7.742a13.84 13.84 0 0 0 .497 -3.753c-.002 -.249 1.51 -2.772 1.818 -4.013z" />
</svg>
@graphicvizion
</a>
</li>
<li>
<a href="https://www.facebook.com/GraphicViZion/" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-facebook" width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M7 10v4h3v7h4v-7h3l1 -4h-4v-2a1 1 0 0 1 1 -1h3v-4h-3a5 5 0 0 0 -5 5v2h-3" />
</svg>
Facebook
</a>
</li>
<li>
<a href="https://www.linkedin.com/company/graphicvizion/" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-linkedin" width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<rect x="4" y="4" width="16" height="16" rx="2" />
<line x1="8" y1="11" x2="8" y2="16" />
<line x1="8" y1="8" x2="8" y2="8.01" />
<line x1="12" y1="16" x2="12" y2="11" />
<path d="M16 16v-3a2 2 0 0 0 -4 0" />
</svg>
LinkedIn
</a>
</li>
<li>
<a href="https://www.youtube.com/user/GraphicVizion" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-youtube"
width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none"
stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<rect x="3" y="5" width="18" height="14" rx="4" />
<path d="M10 9l5 3l-5 3z" />
</svg>
YouTube
</a>
</li>
<li>
<a href="https://itunes.apple.com/us/artist/graphicvizion/id492668041" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-apple" width="32"
height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none"
stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M9 7c-3 0 -4 3 -4 5.5c0 3 2 7.5 4 7.5c1.088 -.046 1.679 -.5 3 -.5c1.312 0 1.5 .5 3 .5s4 -3 4 -5c-.028 -.01 -2.472 -.403 -2.5 -3c-.019 -2.17 2.416 -2.954 2.5 -3c-1.023 -1.492 -2.951 -1.963 -3.5 -2c-1.433 -.111 -2.83 1 -3.5 1c-.68 0 -1.9 -1 -3 -1z" />
<path d="M12 4a2 2 0 0 0 2 -2a2 2 0 0 0 -2 2" />
</svg>
App Store
</a>
</li>
<li>
<a href="https://play.google.com/store/apps/developer?id=GraphicViZion" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-google-play"
width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none"
stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M4 3.71v16.58a0.7 .7 0 0 0 1.05 .606l14.622 -8.42a0.55 .55 0 0 0 0 -.953l-14.622 -8.419a0.7 .7 0 0 0 -1.05 .607z" />
<line x1="15" y1="9" x2="4.5" y2="20.5" />
<line x1="4.5" y1="3.5" x2="15" y2="15" />
</svg>
Play Store
</a>
</li>
<li><a href="<%= site.url %>app/policies/privacypolicy.html" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-eye-off" width="32"
height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none"
stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<line x1="3" y1="3" x2="21" y2="21" />
<path d="M10.584 10.587a2 2 0 0 0 2.828 2.83" />
<path
d="M9.363 5.365a9.466 9.466 0 0 1 2.637 -.365c4 0 7.333 2.333 10 7c-.778 1.361 -1.612 2.524 -2.503 3.488m-2.14 1.861c-1.631 1.1 -3.415 1.651 -5.357 1.651c-4 0 -7.333 -2.333 -10 -7c1.369 -2.395 2.913 -4.175 4.632 -5.341" />
</svg>
Privacy Policy</a></li>
<li><a href="<%= site.url %>app/policies/termsofuse.html" target="_blank"><svg
xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-news" width="32"
height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none"
stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M16 6h3a1 1 0 0 1 1 1v11a2 2 0 0 1 -4 0v-13a1 1 0 0 0 -1 -1h-10a1 1 0 0 0 -1 1v12a3 3 0 0 0 3 3h11" />
<line x1="8" y1="8" x2="12" y2="8" />
<line x1="8" y1="12" x2="12" y2="12" />
<line x1="8" y1="16" x2="12" y2="16" />
</svg>Terms of Use</a></li>
<% sections.forEach((link)=> { %>
<li class="menu-item menu-item--<% link.class %>">
<a href="<% if (link.external) { %><%= link.slug %><% } else { %><%= `../#${link.slug}` %><% } %>">
<%= link.name %>
</a>
</li>
<% }) %>
</ul>
</section>
</footer>

View file

@ -1,19 +1,18 @@
<article class="hero__wrapper"> <article class="hero__wrapper">
<% include /nav %> <%- include('/nav') -%>
<!-- whatever video you put here will be (effectively) cropped to fit container size; make sure you're okay with it shrinking to the top left corner of the video at your specified minimum dimensions --> <!-- whatever video you put here will be (effectively) cropped to fit container size; make sure you're okay with it shrinking to the top left corner of the video at your specified minimum dimensions -->
<video autoplay muted playsinline class="hero__video"> <video autoplay muted playsinline poster="../assets/images/hero.png" class="hero__video">
<source src="../assets/images/hero.mp4" type="video/mp4" alt="HTML5 background video"> <source src="../assets/images/hero.mp4" type="video/mp4" alt="HTML5 background video">
</video> </video>
<!-- <img src="./assets/images/hero.png" class="hero__video">-->
<div class="hero__info"> <div class="hero__info">
<a class="btn btn--hero" href="#download"> <a class="btn btn--hero" href="#download">
download now download now
</a> </a>
<div class="platform-list"> <div class="platform-list">
<% include /store-icons/ios.svg %> <%- include('/store-icons/ios.svg') -%>
<% include /store-icons/android.svg %> <%- include('/store-icons/android.svg') -%>
<% include /store-icons/macos.svg %> <%- include('/store-icons/macos.svg') -%>
<% include /store-icons/windows.svg %> <%- include('/store-icons/windows.svg') -%>
</div> </div>
</div> </div>
<div class="hero__banner"> <div class="hero__banner">

View file

@ -0,0 +1,29 @@
<article class="hero__wrapper">
<%- include('/nav') -%>
<!-- whatever video you put here will be (effectively) cropped to fit container size; make sure you're okay with it shrinking to the top left corner of the video at your specified minimum dimensions -->
<video autoplay muted playsinline poster="../assets/images/hero.png" class="hero__video">
<source src="../assets/images/hero.mp4" type="video/mp4" alt="HTML5 background video">
</video>
<div class="hero__info">
<a class="btn btn--hero" href="#download">
download now
</a>
<div class="platform-list">
<%- include('/store-icons/ios.svg') -%>
<%- include('/store-icons/android.svg') -%>
<%- include('/store-icons/macos.svg') -%>
<%- include('/store-icons/windows.svg') -%>
</div>
</div>
<div class="hero__banner">
<svg class="banner-edge-left" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0.116947"
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" />
</svg>
<svg class="banner-edge-right" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0.116947"
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" />
</svg>
<h1 class="h1--hero">Interactive human anatomy in real-time 3D</h1>
</div>
</article>

View file

@ -0,0 +1,41 @@
<article class="info__wrapper max-w-screen-lg">
<section id="info">
<h1>
Designed for anatomy students
</h1>
<p>
We believe that learning by interaction is the best and easiest way to study human anatomy.
</p>
<h1>
Perfect for professionals
</h1>
<p>
When discussing anatomy with a patient it can help as an visual aid.
</p>
</section>
<section>
<ul>
<li>
over 1200 body parts!
</li>
<li>
highly detailed
</li>
<li>
fully searchable
</li>
<li>
zoom, pan, and rotate in real time
</li>
<li>
show and hide layers
</li>
<li>
see details for each body part
</li>
<li class="hide-on-mobile">
add custom notes
</li>
</ul>
</section>
</article>

View file

@ -118,7 +118,7 @@ pageName: ''
<%- content %> <%- content %>
</main> </main>
<% include /footer %> <%- include('/footer') -%>
</div> </div>
@ -192,7 +192,7 @@ pageName: ''
'http_origin': 'https://visualanatomy3d.app', 'http_origin': 'https://visualanatomy3d.app',
'hash': md5(fromEmail.value + '192y34kjsdf32gt'), /*erkbn234987kjs*/ 'hash': md5(fromEmail.value + '192y34kjsdf32gt'), /*erkbn234987kjs*/
'fromEmail': fromEmail.value, 'fromEmail': fromEmail.value,
'message': message.value, 'message': message.innerText,
'urlUnderneath': 'https://visualanatomy3d.app', 'urlUnderneath': 'https://visualanatomy3d.app',
'title': 'Support - Visual Anatomy 3D (site)' 'title': 'Support - Visual Anatomy 3D (site)'
}; };
@ -233,7 +233,7 @@ pageName: ''
emailError.classList.remove('form-alert--visible'); emailError.classList.remove('form-alert--visible');
otherError.classList.remove('form-alert--visible'); otherError.classList.remove('form-alert--visible');
fromEmail.value = ''; fromEmail.value = '';
message.value = ''; message.innerText = '';
break; break;
case "invalidEmailAdres": case "invalidEmailAdres":
emailError.classList.add('form-alert--visible'); emailError.classList.add('form-alert--visible');
@ -247,7 +247,7 @@ pageName: ''
emailError.classList.remove('form-alert--visible'); emailError.classList.remove('form-alert--visible');
otherError.classList.remove('form-alert--visible'); otherError.classList.remove('form-alert--visible');
fromEmail.value = ''; fromEmail.value = '';
message.value = ''; message.innerText = '';
break; break;
} }
//console.log(data) //console.log(data)

View file

@ -0,0 +1,354 @@
---
pageName: ''
---
<!DOCTYPE html>
<html class="page--<%= pageName %>" lang="en" dir="ltr" style="--scrollbarWidth: 0px; --viewportWidth: calc(100vw - var(--scrollbarWidth));">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="icon" href="/favicon.ico" />
<!-- <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Nunito&family=DM+Serif+Display:ital@0;1&display=swap" rel="stylesheet"> -->
<link rel="preconnect" href="https://api.fonts.coollabs.io" crossorigin>
<link href="https://api.fonts.coollabs.io/css2?family=Bebas+Neue&family=Nunito&family=DM+Serif+Display&display=swap" rel="stylesheet">
<!-- Required Core Stylesheet -->
<!-- <link rel="stylesheet" href="/node_modules/@glidejs/glide/dist/css/glide.core.css"> -->
<!-- Optional Theme Stylesheet -->
<!-- <link rel="stylesheet" href="/node_modules/@glidejs/glide/dist/css/glide.theme.css"> -->
<script>
window.onload = setScrollbarVariable;
document.onload = setScrollbarVariable;
window.onresize = setScrollbarVariable;
function setScrollbarVariable() {
//alert(window.innerWidth + " - " + document.body.clientWidth);
//const scrollbarWidth = window.innerWidth - document.body.clientWidth;
const viewportDependantWidth = (typeof window.orientation !== "undefined") ? screen.width : window.innerWidth;
//console.log(screen.width + " " + window.innerWidth);
const scrollbarWidth = viewportDependantWidth - document.body.clientWidth;
document.documentElement.style.setProperty("--scrollbarWidth", `${scrollbarWidth}px`);
}
</script>
<style>
:root{
--viewportWidth: calc(100vw - var(--scrollbarWidth));
}
</style>
<title>
<%= site.title %>
</title>
<meta name="description" content="<%= (!!locals.description) ? description : site.description %>" />
<meta name="author" content="<%= site.author %>" />
<meta property="og:title" content="<%= site.title %>" />
<meta property="og:description" content="<%= (!!locals.description) ? description : site.description %>" />
<meta property="og:locale" content="<%= site.locale %>" />
<meta property="og:site_name" content="<%= site.site_name %>" />
<!--<script async defer data-website-id="f74324cf-e86f-4993-8537-63ccd9698204" src="https://s9-analytics.altweb.me/umami.js"></script>-->
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-MGE4QXKDFW"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-MGE4QXKDFW');
</script>
<% if (locals.tags=="posts" ) { %>
<meta property="og:type" content="article" />
<meta property="article:published_time" content="<%= date.toISOString() %>" />
<script type="application/ld+json">
{
"description": "<%= (!!locals.description) ? description : site.description %>",
"author": { "@type": "Person", "name": "<%= site.author %>" },
"@type": "BlogPosting",
"url": "<%= `${site.url}${page.url}` %>",
"publisher": {
"@type": "Organization",
"logo": {
"@type": "ImageObject",
"url": "<%= `${site.url}/assets/images/logo.png` %>"
},
"name": "<%= site.author %>"
},
"headline": "<%= site.title %>",
"datePublished": "<%= date.toISOString() %>",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "<%= `${site.url}${page.url}` %>"
},
"@context": "http://schema.org"
}
</script>
<% } %>
<%- include('webpack.ejs') %>
<% if (page.url=="/" ) { %>
<% } %>
</head>
<body>
<div id="page" class="max-w-screen-lg mx-auto">
<header class="site-header ">
<a href="/"><img class="site-logo" src="<%= `/assets/images/logo.png` %>" alt=""></a>
<h1 class="site-title">
<%= site.title %>
</h1>
<!-- <div class="text-xl"><%= site.description %></div> -->
</header>
<main class="page-content">
<%- content %>
</main>
<%- include('/footer') -%>
</div>
<!-- <script src="https://unpkg.com/@glidejs/glide@3.3.0/dist/glide.js"></script> -->
<!-- <script src="/node_modules/@glidejs/glide/dist/glide.modular.esm.js"></script> -->
<!-- <script src="/js/eleventy.js" type="module" async></script> -->
<!-- this below were the last ones that i used -->
<!-- <script src="./node_modules/@glidejs/glide/dist/glide.min.js"></script> -->
<script src="/node_modules/blueimp-md5/js/md5.min.js"></script>
<script>
// new Glide('.glide').mount({
// type: 'carousel',
// startAt: 0,
// perView: 1,
// autoplay: 1000,
// bound: true,
// rewind: false
// })
// new Glide('.glide').mount()
</script>
<script>
var siteUrl = "<%= site.url %>";
console.log(siteUrl);
document.getElementById('fromEmail').addEventListener('input', function () {
const fromEmail = document.getElementById('fromEmail');
const message = document.getElementById('message');
const emailError = document.getElementById('emailError');
const otherError = document.getElementById('otherError');
const success = document.getElementById('success');
const contactSubmit = document.getElementById('contactSubmit');
// if (/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/.test(fromEmail.value)) {
// contactSubmit.disabled = false;
// alert.classList.remove('form-alert--visible');
// } else {
// contactSubmit.disabled = true;
// alert.classList.add('form-alert--visible');
// }
emailError.classList.remove('form-alert--visible');
otherError.classList.remove('form-alert--visible');
success.classList.remove('form-alert--visible');
});
document.getElementById('contactSubmit').addEventListener('click', function () {
const fromEmail = document.getElementById('fromEmail');
const message = document.getElementById('message');
const emailError = document.getElementById('emailError');
const otherError = document.getElementById('otherError');
const success = document.getElementById('success');
if (/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/.test(fromEmail.value)) {
/* succeeded */
emailError.classList.remove('form-alert--visible');
var details = {
'http_origin': 'https://visualanatomy3d.app',
'hash': md5(fromEmail.value + '192y34kjsdf32gt'), /*erkbn234987kjs*/
'fromEmail': fromEmail.value,
'message': message.innerText,
'urlUnderneath': 'https://visualanatomy3d.app',
'title': 'Support - Visual Anatomy 3D (site)'
};
var formBody = [];
for (var property in details) {
var encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
try {
/*siteUrl + 'app/php/email/v1/SendSupportMail.php'*/
fetch('https://graphicvizion.com/apps/php/email/v1/SendSupportMail.php', {
method: 'POST',
//mode: 'no-cors',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formBody,
})
.then(response => {
//console.log("response.status: " + response.status);
if(response.status === 200){
return response.text();
} else {
otherError.classList.add('form-alert--visible');
}
})
.then(data => {
console.log("data:");
console.log(data);
switch (data) {
case "succesSendingSupportEmail":
success.classList.add('form-alert--visible');
emailError.classList.remove('form-alert--visible');
otherError.classList.remove('form-alert--visible');
fromEmail.value = '';
message.innerText = '';
break;
case "invalidEmailAdres":
emailError.classList.add('form-alert--visible');
break;
case "failedSendingSupportEmail":
case "failedHash":
otherError.classList.add('form-alert--visible');
break;
default:
success.classList.add('form-alert--visible');
emailError.classList.remove('form-alert--visible');
otherError.classList.remove('form-alert--visible');
fromEmail.value = '';
message.innerText = '';
break;
}
//console.log(data)
});
} catch (error) {
otherError.classList.add('form-alert--visible');
}
}
else
{
/* failed */
emailError.classList.add('form-alert--visible');
}
});
// https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/flexgap.js
function checkFlexGap() {
// create flex container with row-gap set
var flex = document.createElement("div");
flex.style.display = "flex";
flex.style.flexDirection = "column";
flex.style.rowGap = "1px";
// create two, elements inside it
flex.appendChild(document.createElement("div"));
flex.appendChild(document.createElement("div"));
// append to the DOM (needed to obtain scrollHeight)
document.body.appendChild(flex);
var isSupported = flex.scrollHeight === 1; // flex container should be 1px high from the row-gap
//flex.parentNode.removeChild(flex);
return isSupported;
}
console.log(checkFlexGap());
if (checkFlexGap()) {
document.documentElement.classList.add("flexbox-gap");
} else {
document.documentElement.classList.add("no-flexbox-gap");
}
</script>
</body>
</html>
<!-- <style>
.site-logo {
height: 5rem;
width: 5rem;
transform: rotateZ(0deg) translateY(0.4rem);
transition: 0.2s all;
border: 3px solid var(--c-1);
border-radius: 1rem;
}
.site-logo:hover {
transform: rotateZ(4deg) translateY(0.4rem) scale(1.1);
}
.site-header {
display: flex;
justify-content: center;
align-items: baseline;
gap: 1rem;
}
.no-flexbox-gap .site-header>*:not(:last-child) {
margin-right: 1rem;
}
.site-title {
font-family: Bebas Neue;
font-style: normal;
font-weight: normal;
font-size: 3rem;
line-height: 1;
letter-spacing: 0.24em;
text-transform: uppercase;
width: auto;
margin: 3rem 0 0 0;
}
#page {
display: flex;
flex-direction: column;
align-items: center;
}
.page-content {
display: flex;
flex-direction: column;
align-items: center;
}
</style> -->

View file

@ -5,26 +5,26 @@ layout: layouts/base.ejs
<span>asdf</span> <span>asdf</span>
<%= 'hello' | i18n %> <%= 'hello' | i18n %>
<% include /hero %> <%- include('/hero') -%>
<% include /blurb %> <%- include('/blurb') -%>
<div class="inset"> <div class="inset">
<% include /info %> <%- include('/info') -%>
</div> </div>
<% include /screenshots %> <%- include('/screenshots') -%>
<% include /systems %> <%- include('/systems') -%>
<div class="inset"> <div class="inset">
<% include /pricing %> <%- include('/pricing') -%>
<% include /download %> <%- include('/download') -%>
</div> </div>
<% include /reviews %> <%- include('/reviews') -%>

View file

@ -0,0 +1,30 @@
---
layout: layouts/base.ejs
---
<span>asdf</span>
<%= 'hello' | i18n %>
<%- include('/hero') -%>
<%- include('/blurb') -%>
<div class="inset">
<%- include('/info') -%>
</div>
<%- include('/screenshots') -%>
<%- include('/systems') -%>
<div class="inset">
<%- include('/pricing') -%>
<%- include('/download') -%>
</div>
<%- include('/reviews') -%>

View file

@ -2,7 +2,7 @@
layout: layouts/base.ejs layout: layouts/base.ejs
pageName: post pageName: post
--- ---
<% include /nav-blog %> <%- include('/nav-blog') -%>
<article id="post"> <article id="post">
<header class="post__header hero__wrapper"> <header class="post__header hero__wrapper">
<img class="post__image" src="/assets/images/posts/<%= image %>" /> <img class="post__image" src="/assets/images/posts/<%= image %>" />

View file

@ -0,0 +1,34 @@
---
layout: layouts/base.ejs
pageName: post
---
<%- include('/nav-blog') -%>
<article id="post">
<header class="post__header hero__wrapper">
<img class="post__image" src="/assets/images/posts/<%= image %>" />
<div class="hero__banner">
<svg class="banner-edge-left" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0.116947"
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" />
</svg>
<svg class="banner-edge-right" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0.116947"
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" />
</svg>
<h1 class="">
<%= title %>
</h1>
<time class="">
<%= this.dateFns.format(new Date(date), 'yyyy.LL.dd' ) %>
</time>
</div>
<% if (locals.intro) { %>
<div class="post__intro">
<%= intro %>
</div>
<% } %>
</header>
<section class="post__content">
<%- content %>
</section>
</article>

View file

@ -0,0 +1,5 @@
<link
href="/assets/styles/main.css"
rel="stylesheet"
/>
<!-- needed to add ./ the href, or else the path was wrong on production -->

View file

@ -0,0 +1,29 @@
<div class="nav__wrapper">
<nav>
<ul>
<li>
<a class="nav-link" href="/blog/">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-arrow-left" width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<line x1="5" y1="12" x2="19" y2="12" />
<line x1="5" y1="12" x2="11" y2="18" />
<line x1="5" y1="12" x2="11" y2="6" />
</svg> see more posts
</a>
</li>
<li>
<a class="nav-link nav-link--blog" href="/">
home
</a>
</li>
</ul>
</nav>
<svg class="nav-edge-left" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0"
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" />
</svg>
<svg class="nav-edge-right" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0"
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" />
</svg>
</div>

21
src/_includes/nav.ejs.bak Normal file
View file

@ -0,0 +1,21 @@
<div class="nav__wrapper">
<nav>
<ul>
<% sections.filter((item)=>{ return item.inNav == true; }).forEach((link)=> { %>
<li>
<a class="nav-link nav-link--<%= link.class %>" href="<% if (link.external) { %><%= link.slug %><% } else { %><%= `#${link.slug}` %><% } %>">
<%= link.name %>
</a>
</li>
<% }) %>
</ul>
</nav>
<svg class="nav-edge-left" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0"
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" />
</svg>
<svg class="nav-edge-right" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0"
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" />
</svg>
</div>

View file

@ -0,0 +1,220 @@
<article class="pricing__wrapper max-w-screen-lg">
<header>
<h1 id="pricing">
flexible pricing options
</h1>
<aside>
Our <%= site.site_name %> app is available for <strong>free download</strong>. By subscribing, you'll unlock all of the advanced features and systems.
While our app is not currently not cross-platform, you can easily share your subscription across multiple devices on the same platform.
Subscribing to our app gives you access to all the features and systems for a low monthly fee of just $7, or an even better value yearly subscription of $17 (that's <strong>less than $1.50 per month!</strong>).
</aside>
</header>
<section class="pricing__content">
<div class="level__wrapper level-wrapper--heading">
<header>
<!-- <h2>
<span>
</span>
</h2>-->
</header>
<div class="level__content">
<div class="level__price-wrapper">
<!--<h2 class="level__price">
</h2>
<span>
</span>-->
</div>
<ul>
<% systems.forEach((system)=> { %>
<li class="">
<%= system.name %>
</li>
<% }) %>
</ul>
</div>
<div></div>
</div>
<div class="level__wrapper level-wrapper--trial">
<header>
<h2>
starter
<span>
limited
</span>
</h2>
</header>
<div class="level__content">
<div class="level__price-wrapper">
<!--<h2 class="level__price" style="align-items: center;">
<span>
</span>
</h2>-->
</div>
<ul>
<!-- <li>2 systems included</li>
<li>purchase advanced systems separately</li> -->
<% systems.forEach((system)=> { %>
<% if (system.status==='free' ) { %>
<li><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="32" height="32" viewBox="0 0 24 24" stroke-width="3" stroke="#00C2FF" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M5 12l5 5l10 -10" />
</svg></li>
<% } else if (system.status==='pro' ) { %>
<li><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-x" width="32" height="32" viewBox="0 0 24 24" stroke-width="3" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg><!--<span>(in-app purchase)</span>--></li>
<% } else if (system.status==='soon' ) { %>
<li><span>(coming soon)</span></li>
<% } %>
<% }) %>
</ul>
</div>
<!-- <a class="btn btn--level" href="#download">
download
</a>-->
</div>
<div class="level__wrapper level__wrapper--monthly level__wrapper--enabled">
<header>
<h2>
Premium
<span>
full
</span>
</h2>
</header>
<div class="level__content">
<div class="level__price-wrapper">
<!-- <h2 class="level__price">
span>
monthly $7 / yearly $17 / lifetime $27
</span>
</h2>-->
</div>
<ul>
<% systems.forEach((system)=> { %>
<% if (system.status==='pro' || system.status==='free' ) { %>
<li><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="32" height="32" viewBox="0 0 24 24" stroke-width="3" stroke="#00C2FF" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M5 12l5 5l10 -10" />
</svg>
</li>
<% } else if (system.status==='soon' ) { %>
<li><span>(coming soon)</span></li>
<% } %>
<% }) %>
</ul>
</div>
<!--<a class="btn btn--level btn--disabled">
coming soon
</a>-->
</div>
<!--<div class="level__wrapper level__wrapper--yearly level__wrapper--disabled">
<header>
<h2>
yearly
<span>
subscription
</span>
</h2>
</header>
<div class="level__content">
<div class="level__price-wrapper">
<h2 class="level__price">
$3.95
<span>
paid monthly
</span>
</h2>
</div>
<ul>
<% systems.forEach((system)=> { %>
<% if (system.status==='pro' || system.status==='free' ) { %>
<li><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="32" height="32" viewBox="0 0 24 24" stroke-width="3" stroke="#00C2FF" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M5 12l5 5l10 -10" />
</svg></li>
<% } else if (system.status==='soon' ) { %>
<li><span class="">(coming soon)</span></li>
<% } %>
<% }) %>
</ul>
</div>
<a class="btn btn--level btn--disabled">
coming soon
</a>
</div>
<div class="level__wrapper level__wrapper--lifetime">
<header>
<h2>
lifetime
<span>
full version
</span>
</h2>
</header>
<div class="level__content">
<div class="level__price-wrapper">
<h2 class="level__price">
$24.95
<span>
one time fee
</span>
</h2>
</div>
<ul>
<% systems.forEach((system)=> { %>
<% if (system.status==='pro' || system.status==='free' ) { %>
<li><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="32" height="32" viewBox="0 0 24 24" stroke-width="3" stroke="#00C2FF" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M5 12l5 5l10 -10" />
</svg></li>
<% } else if (system.status==='soon' ) { %>
<li><span>(coming soon)</span></li>
<% } %>
<% }) %>
</ul>
</div>
<a class="btn btn--level" href="#download">
download
</a>
</div>-->
</section>
</article>

View file

@ -0,0 +1,36 @@
<article class="reviews-wrapper">
<header>
<h1 id="reviews">
Glowing reviews
</h1>
</header>
<section>
<ul class="reviews">
<% reviews.forEach((review)=> { %>
<li class="review">
<div class="rating-wrapper">
<div class="rating">
<% for (let step=0; step <=review.stars * 10; step +=5) { %>
<% if (step> 0) { %>
<label class="<%= (step % 2 == 0) ? 'full' : 'half' %> <%= step %>"></label>
<% } %>
<% } %>
<% if (review.stars * 10 % 2 !==0) { %>
<label class="full" style="color: transparent"></label>
<% } %>
</div>
<a href="<%= review.link %>">
<%= review.site %>
</a>
</div>
<blockquote>
<%= review.quote %>
</blockquote>
<label class="review__name">
<%= review.name %>
</label>
</li>
<% }) %>
</ul>
</section>
</article>

View file

@ -0,0 +1,65 @@
<article class="screenshots__wrapper">
<header>
<h1 id="screenshots">
Hi-res imagery everywhere you need it
</h1>
<aside>
The <%= site.site_name %> app is currently available for iOS and Android, with desktop support added later.
The app supports portrait mode, text-scaling, and it includes 3 color themes.
</aside>
</header>
<section>
<div class="glide">
<div data-glide-el="track" class="glide__track">
<ul class="glide__slides">
<% collections.screenshotThumbnails.forEach((screenshot, index)=> { %>
<% if (screenshot.includes('--en')) { %>
<li class="glide__slide">
<img src="<%= screenshot %>" alt="" onclick="zoomScreenshot('<%= screenshot %>')" />
</li>
<% } %>
<% }) %>
</ul>
</div>
</div>
<div class="hires">
<% collections.screenshotHires.forEach((screenshot, index)=> { %>
<% if (screenshot.includes('--en')) { %>
<div class="hires-details" data="<%= screenshot %>" onclick="clearScreenshotSelection()">
<img src="<%= screenshot %>" alt="" />
<caption></caption>
</div>
<% } %>
<% }) %>
</div>
</section>
</article>
<script>
function zoomScreenshot(slug) {
let thisImage = document.querySelector('[data="' + slug.replace('resized.','') + '"]');
thisImage.classList.add('hires-details--selected');
let allIconImages = document.querySelectorAll('.hires-details');
for (let elem of allIconImages) {
if (elem !== thisImage) {
elem.classList.remove('hires-details--selected')
}
}
}
function clearScreenshotSelection() {
let allIconImages = document.querySelectorAll('.hires-details');
for (let elem of allIconImages) {
elem.classList.remove('hires-details--selected')
}
}
</script>

View file

@ -0,0 +1,69 @@
<article class="system__wrapper">
<header>
<h1 id="systems">
<%= systems.filter(system => system.status !== 'soon').length %> detailed body systems
</h1>
<aside>
The <%= site.site_name %> app includes <strong><%= systems.filter(system => system.status !== 'soon').length %></strong> body systems, which can be hidden or shown (in layers) and colored to easily distinguish the individual anatomical parts.
All body systems can be viewed individually or in customizable combinations.
</aside>
</header>
<section>
<ul class="system__list">
<% systems.forEach((system, index)=> { %>
<li onclick="zoom('<%= system.slug %>')"
class="system system--<%= system.slug %> system--<%= system.status %> <%= index === 0 ? 'system--selected' : '' %>">
<%- include('/system-icons/'+system.slug+'.svg') %>
<span>
<%= system.name %>
</span>
</li>
<% }) %>
</ul>
<div class="system__zoom-wrapper">
<img class="zoom__image--bkg %>"
src="./assets/images/systems/layers/bkg.png" alt="background">
<% systems.filter(system => system.status !== 'soon').forEach((system, index)=> { %>
<img class="zoom__image zoom__image--<%= system.slug %> <%= index === 0 ? 'zoom__image--visible' : '' %>"
src="./assets/images/systems/layers/<%= system.slug %>.png" alt="<%= system.name %>"
title="<%= system.name %>">
<% }) %>
</div>
</section>
</article>
<script>
function zoom(slug) {
const thisIconClass = 'system--' + slug;
let thisIconImage = document.querySelector('.' + thisIconClass);
thisIconImage.classList.add('system--selected')
let allIconImages = document.querySelectorAll('.system');
for (let elem of allIconImages) {
if (!elem.classList.contains(thisIconClass)) {
elem.classList.remove('system--selected')
}
}
const thisZoomClass = 'zoom__image--' + slug;
let thisZoomImage = document.querySelector('.' + thisZoomClass);
thisZoomImage.classList.add('zoom__image--visible')
let allZoomImages = document.querySelectorAll('.zoom__image');
for (let elem of allZoomImages) {
if (!elem.classList.contains(thisZoomClass)) {
elem.classList.remove('zoom__image--visible')
}
}
}
</script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 895 KiB

After

Width:  |  Height:  |  Size: 1,006 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 895 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

42
src/blog.ejs.bak Normal file
View file

@ -0,0 +1,42 @@
---
pagination:
data: collections.posts
size: 20
alias: list
reverse: true
permalink: '<% if (pagination.pageNumber > 0) { %><%= `blog/page${pagination.pageNumber + 1}/index.html` %><% } else { %>blog/index.html<% } %>'
eleventyComputed:
title: '<% if (pagination.pageNumber > 0) { %><%= `Page ${pagination.pageNumber + 1} | ${site.title}` %><% } else { %><%= site.title %><% } %>'
pageName: blog
---
<h2 class="blog-header">
Blog
</h2>
<ul id="blogs">
<% list.forEach((post) => { %>
<li class="blog">
<a href="<%= post.url %>">
<article>
<img src="/assets/images/posts/<%= post.data.image %>" alt="">
<h1><%= post.data.title %></h1>
<time datetime="<%= new Date(post.data.date) %>"><%= this.dateFns.format(new Date(post.data.date), 'LLLL d, yyyy') %></time>
<p><%= post.data.description %></p>
</article>
</a>
</li>
<% }) %>
</ul>
<div class="">
<% if (pagination.previous) { %>
<div>
<a href="<%= pagination.previous.replace(/index.html$/, "") %>">← Newer Posts</a>
</div>
<% } %> <% if (pagination.next) { %>
<div class="">
<a href="<%= pagination.next.replace(/index.html$/, "") %>">Older Posts →</a>
</div>
<% } %>
</div>

3
src/en-US/index.ejs.bak Normal file
View file

@ -0,0 +1,3 @@
---
layout: layouts/home.ejs
---

View file

@ -4,28 +4,28 @@ layout: layouts/base.ejs
pageName: home pageName: home
--- ---
<% include /hero %> <%- include('/hero') -%>
<% include /blurb %> <%- include('/blurb') -%>
<div class="inset"> <div class="inset">
<% include /info %> <%- include('/info') -%>
</div> </div>
<% include /screenshots %> <%- include('/screenshots') -%>
<% include /systems %> <%- include('/systems') -%>
<div class="inset"> <div class="inset">
<% include /pricing %> <%- include('/pricing') -%>
<% include /download %> <%- include('/download') -%>
</div> </div>
<% include /reviews %> <%- include('/reviews') -%>
<% include /contact %> <%- include('/contact') -%>

31
src/index.ejs.bak Normal file
View file

@ -0,0 +1,31 @@
---
title: '<%= site.title %>'
layout: layouts/base.ejs
pageName: home
---
<%- include('/hero') -%>
<%- include('/blurb') -%>
<div class="inset">
<%- include('/info') -%>
</div>
<%- include('/screenshots') -%>
<%- include('/systems') -%>
<div class="inset">
<%- include('/pricing') -%>
<%- include('/download') -%>
</div>
<%- include('/reviews') -%>
<%- include('/contact') -%>

7
src/robots.ejs.bak Normal file
View file

@ -0,0 +1,7 @@
---
permalink: robots.txt
eleventyExcludeFromCollections: true
layout: null
---
Sitemap: <%= `${site.url}/sitemap.xml` %>

14
src/sitemap.ejs.bak Normal file
View file

@ -0,0 +1,14 @@
---
permalink: sitemap.xml
eleventyExcludeFromCollections: true
layout: null
---
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<% collections.all.forEach((page) => { %>
<url>
<loc><%= `${site.url}${page.url}` %></loc>
</url>
<% }) %>
</urlset>