kasha
Version:
Pre-render your Single-Page Application.
317 lines (269 loc) • 9.24 kB
HTML
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Kasha</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="/static/kasha.png">
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
.textbox, .select{
border: 1px solid #ccc;
border-radius: 2px;
height: 30px;
}
.textbox:disabled, .select:disabled {
background-color: #ebebe4;
}
/* from https://medium.com/claritydesignsystem/pure-css-accessible-checkboxes-and-radios-buttons-54063e759bb3 */
.checkbox {
position: absolute;
left: -99999px;
top: -99999px;
opacity: 0;
}
.checkbox + label {
position: relative;
display: inline-block;
/*16px width of fake checkbox + 6px distance between fake checkbox and text*/
padding-left: 22px;
}
.checkbox + label::before,
.checkbox + label::after {
position: absolute;
content: "";
/*Needed for the line-height to take effect*/
display: inline-block;
}
/*Outer box of the fake checkbox*/
.checkbox + label::before{
height: 16px;
width: 16px;
border: 1px solid #ccc;
border-radius: 2px;
left: 0px;
/*(24px line-height - 16px height of fake checkbox) / 2 - 1px for the border
*to vertically center it.
*/
top: 3px;
}
/*Checkmark of the fake checkbox*/
.checkbox + label::after {
height: 5px;
width: 9px;
border-left: 2px solid #377ef0;
border-bottom: 2px solid #377ef0;
transform: rotate(-45deg);
left: 4px;
top: 7px;
}
/*Hide the checkmark by default*/
.checkbox + label::after {
content: none;
}
/*Unhide on the checked state*/
.checkbox:checked + label::after {
content: "";
}
/*Adding focus styles on the outer-box of the fake checkbox*/
.checkbox:focus + label::before {
outline: #4d90fe auto 5px;
}
.checkbox:disabled + label::before {
background-color: #ebebe4;
}
.form {
width: fit-content;
text-align: center;
margin: 90px auto;
}
.address-box {
border: none;
border-radius: 2px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.2);
width: 600px;
height: 40px;
padding-left: 1em;
padding-right: 1em;
box-sizing: border-box;
}
.address-box:hover, .address-box:focus {
box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.2);
}
.btn-render {
width: 76px;
height: 42px;
margin-left: 4px;
background-color: #377ef0;
border: 1px solid #377ef0;
border-radius: 2px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16);
color: #fff;
font-weight: bold;
cursor: pointer;
}
.btn-render:hover, .btn-render:focus {
box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.2);
}
.fieldset {
text-align: left;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 2px;
padding: 8px 16px 16px;
}
.opt {
margin: 6px 0;
}
.callback-url-textbox {
width: 500px;
}
</style>
</head>
<body>
<form name="render" action="render" method="get" class="form" target="_blank">
<img src="/static/kasha.svg" alt="kasha logo" width="200">
<h1>Kasha</h1>
<input type="url" name="url" required placeholder="https://www.example.com/" class="address-box"><button type="submit" class="btn-render">Render</button>
<fieldset class="fieldset">
<legend>Options</legend>
<div class="opt"><input type="checkbox" class="checkbox" name="fallback" value="" id="fallback"><label for="fallback">fallback</label></div>
<div class="opt"><input type="checkbox" class="checkbox" name="refresh" value="" id="refresh"><label for="refresh">refresh</label></div>
<div class="opt"><input type="checkbox" class="checkbox" name="metaOnly" value="" id="metaOnly"><label for="metaOnly">metaOnly</label></div>
<div class="opt"><input type="checkbox" class="checkbox" name="noWait" value="" id="noWait"><label for="noWait">noWait</label></div>
<div class="opt"><input type="checkbox" class="checkbox" name="followRedirect" value="" id="followRedirect"><label for="followRedirect">followRedirect</label></div>
<div class="opt">
<label>type:
<select name="type" class="select">
<option value="json">json</option>
<option value="html">html</option>
<option value="static">static (js stripped html)</option>
</select>
</label>
</div>
<div class="opt">
<label>profile: <input type="text" name="profile" placeholder="desktop" class="textbox"></label>
</div>
<div class="opt"><label>callbackURL: <input type="url" name="callbackURL" placeholder="https://api.example.com/callback" class="textbox callback-url-textbox"></label></div>
</fieldset>
<fieldset class="fieldset">
<legend>Sitemaps</legend>
<ul>
<li><a href="#" data-href="/robots.txt" target="_blank">/robots.txt</a></li>
<li><a href="#" data-href="/sitemap.index.1.xml" target="_blank">/sitemap.index.1.xml</a></li>
<li><a href="#" data-href="/sitemap.index.google.1.xml" target="_blank">/sitemap.index.google.1.xml</a></li>
<li><a href="#" data-href="/sitemap.index.google.news.1.xml" target="_blank">/sitemap.index.google.news.1.xml</a></li>
<li><a href="#" data-href="/sitemap.index.google.image.1.xml" target="_blank">/sitemap.index.google.image.1.xml</a></li>
<li><a href="#" data-href="/sitemap.index.google.video.1.xml" target="_blank">/sitemap.index.google.video.1.xml</a></li>
<li><a href="#" data-href="/sitemap.1.xml" target="_blank">/sitemap.1.xml</a></li>
<li><a href="#" data-href="/sitemap.google.1.xml" target="_blank">/sitemap.google.1.xml</a></li>
<li><a href="#" data-href="/sitemap.google.news.1.xml" target="_blank">/sitemap.google.news.1.xml</a></li>
<li><a href="#" data-href="/sitemap.google.image.1.xml" target="_blank">/sitemap.google.image.1.xml</a></li>
<li><a href="#" data-href="/sitemap.google.video.1.xml" target="_blank">/sitemap.google.video.1.xml</a></li>
<li><a href="#" data-href="/sitemap.debug" data-append-path target="_blank">/sitemap.debug</a></li>
</ul>
</fieldset>
</form>
<script>
const form = document.forms.render.elements
;[form.fallback, form.refresh, form.metaOnly, form.noWait, form.type, form.callbackURL].forEach(el =>
el.addEventListener('change', updateInputsState)
)
function updateInputsState() {
if (this !== form.fallback) {
if (form.type.value !== 'html' || form.refresh.checked || form.noWait.checked || form.callbackURL.value) {
form.fallback.disabled = true
form.fallback.checked = false
} else {
form.fallback.disabled = false
}
}
if (this !== form.refresh) {
if (form.fallback.checked) {
form.refresh.disabled = true
form.refresh.checked = false
} else {
form.refresh.disabled = false
}
}
if (this !== form.metaOnly) {
if (form.type.value !== 'json' || form.noWait.checked) {
form.metaOnly.disabled = true
form.metaOnly.checked = false
} else {
form.metaOnly.disabled = false
}
}
if (this !== form.noWait) {
if (form.fallback.checked || form.callbackURL.value) {
form.noWait.disabled = true
form.noWait.checked = false
} else {
form.noWait.disabled = false
}
}
if (this !== form.type) {
if (form.fallback.checked) {
form.type.value = 'html'
form.type.options[0].disabled = form.type.options[2].disabled = true
} else if (form.metaOnly.checked) {
form.type.disabled = true
form.type.value = 'json'
} else if (form.noWait.checked) {
form.type.disabled = true
form.type.value = 'json'
} else if (form.callbackURL.value) {
form.type.disabled = true
form.type.value = 'json'
} else {
form.type.disabled = false
form.type.options[0].disabled =
form.type.options[1].disabled =
form.type.options[2].disabled = false
}
}
if (this !== form.callbackURL) {
if (form.fallback.checked || form.noWait.checked || ['html', 'static'].includes(form.type.value)) {
form.callbackURL.disabled = true
form.callbackURL.value = ''
} else {
form.callbackURL.disabled = false
}
}
}
const urlInput = form.url
const sitemapLinks = document.querySelectorAll('a[data-href]')
for (const link of sitemapLinks) {
link.addEventListener('click', e => {
if (!urlInput.reportValidity()) {
e.preventDefault()
}
})
}
urlInput.addEventListener('change', function() {
let url
try {
url = new URL(this.value)
} catch (e) {}
for (const link of sitemapLinks) {
if (url) {
if (link.dataset.appendPath === '') {
link.href = `/${url.origin}${link.dataset.href}${url.pathname}`
link.textContent = `${link.dataset.href}${url.pathname}`
} else {
link.href = `/${url.origin}${link.dataset.href}`
}
} else {
link.href = '#'
if (link.dataset.appendPath === '') {
link.textContent = link.dataset.href
}
}
}
})
</script>
</body>
</html>