Wrangle up some CSS
parent
9dcee48717
commit
73a1576233
|
@ -32,13 +32,12 @@ async function filter_asset(src) {
|
||||||
let type = await filetype.fromBuffer(content);
|
let type = await filetype.fromBuffer(content);
|
||||||
if(typeof type === "undefined") {
|
if(typeof type === "undefined") {
|
||||||
// Failed, try to extract from the URL
|
// Failed, try to extract from the URL
|
||||||
let match = src.match(/(?<=\.)[a-zA-Z0-9-_]$/);
|
let match = src.match(/(?<=\.)[a-zA-Z0-9-_]+$/);
|
||||||
// Failed, just go with no file type extension at all
|
// Failed, just go with no file type extension at all
|
||||||
if(match === null) match = [ null, "" ];
|
if(match === null) match = [ null, "" ];
|
||||||
type = { ext: match[1] }
|
type = { ext: match[0] };
|
||||||
}
|
}
|
||||||
if(type.ext.length > 0) type.ext = `.${type.ext}`;
|
if(type.ext.length > 0) type.ext = `.${type.ext}`;
|
||||||
|
|
||||||
// It's a URL - download it
|
// It's a URL - download it
|
||||||
filename = `${hash(src)}${type.ext}`;
|
filename = `${hash(src)}${type.ext}`;
|
||||||
await fs.promises.writeFile(
|
await fs.promises.writeFile(
|
||||||
|
|
|
@ -37,23 +37,25 @@ description: "Hull Blogs provides aggregated content from University of Hull stu
|
||||||
</a></h1>
|
</a></h1>
|
||||||
<p>{{ tagline }}</p>
|
<p>{{ tagline }}</p>
|
||||||
</header>
|
</header>
|
||||||
<nav class="shadow-bottom">
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
{% for navitem in collections.navigable %}
|
{% for navitem in collections.navigable %}
|
||||||
<li {% if page.url == navitem.url %}aria-current="page"{% endif %}>
|
<li {% if page.url == navitem.url %}aria-current="page"{% endif %}>
|
||||||
<a href="{{ navitem.url }}" class="nav">{{ navitem.data.title }}</a>
|
<a href="{{ navitem.url }}" class="nav invisilink">{{ navitem.data.title }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<li><a href="https://github.com/sbrl/Minetest-WorldEditAdditions/" class="nav image"><img src="{% asset 'images/github.svg' %}" alt="GitHub" title="GitHub" /></a></li>
|
<li><a href="https://github.com/sbrl/Minetest-WorldEditAdditions/" class="nav image"><img class="large-icon invert-when-light" src="{% asset 'images/github.svg' %}" alt="GitHub" title="GitHub" /></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<main>
|
||||||
{{ content | safe }}
|
{{ content | safe }}
|
||||||
|
</main>
|
||||||
|
|
||||||
<footer class="shadow-top">
|
<footer class="shadow-top">
|
||||||
<p>hullblogs.com built with ❤️ by <a href="https://starbeamrainbowlabs.com/"><img src="{% asset 'https://starbeamrainbowlabs.com/images/sbrl/SBRL-Small-200.png' %}" alt="Starbeamrainbowlabs' logo" aria-hidden="true" />Starbeamrainbowlabs</p>
|
<p>hullblogs.com built with ❤️ by <a href="https://starbeamrainbowlabs.com/"><img class="large-icon" src="{% asset 'https://starbeamrainbowlabs.com/images/sbrl/SBRL-Small-200.png' %}" alt="Starbeamrainbowlabs' logo" aria-hidden="true" />Starbeamrainbowlabs</p>
|
||||||
|
|
||||||
<p>Tech: <a href="https://www.11ty.dev/">Eleventy</a> (this website), <a href="https://www.heropatterns.com/">Hero Patterns</a> (background patterns), <a href="https://github.com/shssoichiro/oxipng">Oxipng</a> (PNG image compression), <a href="https://www.npmjs.com/package/feedme"><code>feedme</code></a> (for prsing feeds)</p>
|
<p>Tech: <a href="https://www.11ty.dev/">Eleventy</a> (this website), <a href="https://useiconic.com/open">Open Iconic</a> (icons)<!--, <a href="https://www.heropatterns.com/">Hero Patterns</a> (background patterns)-->, <a href="https://github.com/shssoichiro/oxipng">Oxipng</a> (PNG image compression), <a href="https://www.npmjs.com/package/feedme"><code>feedme</code></a> (for prsing feeds)</p>
|
||||||
<p>Licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache Licence 2.0</a> (<a href="https://tldrlegal.com/license/apache-license-2.0-(apache-2.0)">tldr</a>)</p>
|
<p>Licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache Licence 2.0</a> (<a href="https://tldrlegal.com/license/apache-license-2.0-(apache-2.0)">tldr</a>)</p>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -0,0 +1,255 @@
|
||||||
|
/* Base CSS */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This CSS file contains (for me) logical style defaults that are easy to read.
|
||||||
|
*
|
||||||
|
* This file is quite often used as a starting point for other projects.
|
||||||
|
*
|
||||||
|
* Todo:
|
||||||
|
* <button>
|
||||||
|
* <inputs>
|
||||||
|
* <progress>
|
||||||
|
* <meter>
|
||||||
|
*/
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--bg-main: #f3f3f3;
|
||||||
|
--bg-bright: #fe6330;
|
||||||
|
|
||||||
|
--text-main: #232323;
|
||||||
|
--text-alt: #515151;
|
||||||
|
|
||||||
|
--shadow: hsla(0, 0%, 25%, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--bg-main: #232323;
|
||||||
|
|
||||||
|
--text-main: #f3f3f3;
|
||||||
|
--text-alt: #f3f3f3;
|
||||||
|
|
||||||
|
--shadow: hsla(0, 0%, 100%, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.invert-when-dark {
|
||||||
|
filter: invert(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media not (prefers-color-scheme: dark) {
|
||||||
|
.invert-when-light {
|
||||||
|
filter: invert(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rem is relative to the html element, and em is relative to the current element. */
|
||||||
|
html, body { font-size: 100%; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
body
|
||||||
|
{
|
||||||
|
font-family: "Open Sans", "Roboto", "Helvetica", sans-serif; /* Serif is awful :( */
|
||||||
|
|
||||||
|
background: var(--bg-main); /* Don't forget to update the @page one too for paged media */
|
||||||
|
color: var(--text-main);
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 10% auto 10%;
|
||||||
|
grid-template-rows: auto auto auto auto;
|
||||||
|
grid-template-areas: "header header header"
|
||||||
|
"nav nav nav"
|
||||||
|
". content ."
|
||||||
|
"footer footer footer";
|
||||||
|
}
|
||||||
|
|
||||||
|
title { string-set: page-title content(text); }
|
||||||
|
|
||||||
|
/* Special tweaks for paged media (e.g. PDFs) */
|
||||||
|
@page {
|
||||||
|
font-family: sans-serif;
|
||||||
|
background: var(--bg-main); /* Set the background colour to cover the whole page */
|
||||||
|
|
||||||
|
@top-left {
|
||||||
|
content: string(page-title);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
@top-right {
|
||||||
|
content: "Hull Blogs";
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
@bottom-right {
|
||||||
|
content: "Page " counter(page) " of " counter(pages);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
grid-area: header;
|
||||||
|
background: var(--text-main);
|
||||||
|
color: var(--bg-bright);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
body > nav {
|
||||||
|
grid-area: nav;
|
||||||
|
background: var(--text-main);
|
||||||
|
color: var(--bg-bright);
|
||||||
|
}
|
||||||
|
body > nav > ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
font-size: 1.25em; font-weight: bold;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
body > nav > ul > li {
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
grid-area: content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.posts {
|
||||||
|
margin: 2em 0;
|
||||||
|
}
|
||||||
|
.posts > :nth-child(even) {
|
||||||
|
background: var(--shadow);
|
||||||
|
}
|
||||||
|
.post {
|
||||||
|
--margin-vertical-content: 1rem;
|
||||||
|
margin: 2em 0;
|
||||||
|
padding: 0 var(--margin-vertical-content) 0 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 25% auto;
|
||||||
|
grid-template-rows: auto auto auto;
|
||||||
|
grid-template-areas: "image title"
|
||||||
|
"image content"
|
||||||
|
"image footer";
|
||||||
|
}
|
||||||
|
|
||||||
|
.post > h2 { margin: var(--margin-vertical-content) 0 0 0; grid-area: title; }
|
||||||
|
.post > .post-image {
|
||||||
|
grid-area: image;
|
||||||
|
/* HACK: Using !important should be done *very* sparingly */
|
||||||
|
background-size: cover !important;
|
||||||
|
background-position: center center !important;
|
||||||
|
background-repeat: no-repeat !important;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
.post > .post-extract {
|
||||||
|
grid-area: content;
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
.post > .post-footer {
|
||||||
|
grid-area: footer;
|
||||||
|
margin: 0 0 var(--margin-vertical-content) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.pagination {
|
||||||
|
margin: 5em 0 0 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
background: var(--text-alt);
|
||||||
|
color: var(--bg-bright);
|
||||||
|
}
|
||||||
|
nav.pagination > span {
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
nav.paginatioon > span[aria-current] {
|
||||||
|
font-weight: bolder;
|
||||||
|
font-size: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
padding-bottom: 3em;
|
||||||
|
grid-area: footer;
|
||||||
|
background: var(--bg-bright);
|
||||||
|
color: var(--text-alt);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:not(.invisilink) { font-weight: bold; color: var(--bg-bright); }
|
||||||
|
a:not(.invisilink):hover { color: hsl(14, 99%, 52%); }
|
||||||
|
a:not(.invisilink):active { color: hsl(14, 99%, 46%); }
|
||||||
|
a:not(.invisilink):visited { color: hsl(14, 98%, 40%); }
|
||||||
|
|
||||||
|
/* A small tweak to things more responsive */
|
||||||
|
iframe, object, embed, img, table, video, audio
|
||||||
|
{
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Turn the user's cursor into a hand when over things they can click */
|
||||||
|
button, summary
|
||||||
|
{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td
|
||||||
|
{
|
||||||
|
margin: 4px 6px;
|
||||||
|
padding: 4px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre { page-break-inside: avoid; break-inside: avoid; }
|
||||||
|
pre, code {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* todo add the rest of the textbox like inputs here */
|
||||||
|
input[type=text], input[type=number], textarea
|
||||||
|
{
|
||||||
|
margin: 3px 5px;
|
||||||
|
padding: 5px 8px;
|
||||||
|
|
||||||
|
background: var(--bg-bright);
|
||||||
|
border: 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utility / layout aids */
|
||||||
|
.float.left { float: left; }
|
||||||
|
.float.right { float: right; }
|
||||||
|
|
||||||
|
.flex { display: flex; }
|
||||||
|
.flex-1 { flex: 1; }
|
||||||
|
.flex-2 { flex: 2; }
|
||||||
|
.flex-3 { flex: 3; }
|
||||||
|
.flex-4 { flex: 4; }
|
||||||
|
.flex-5 { flex: 5; }
|
||||||
|
.flex-6 { flex: 6; }
|
||||||
|
|
||||||
|
.small-spacing { margin: 0.25em 0.35em; padding: 0.25em 0.35em; }
|
||||||
|
.med-spacing { margin: 0.45em 0.65em; padding: 0.45em 0.65em; }
|
||||||
|
.high-spacing { margin: 1em 1.25em; padding: 1em 1.25em; }
|
||||||
|
|
||||||
|
.text-left { text-align: left; }
|
||||||
|
.text-centre { text-align: center; }
|
||||||
|
.text-right { text-align: right; }
|
||||||
|
|
||||||
|
.small-text { font-size: 0.8rem; }
|
||||||
|
.medium-text { font-size: 1rem; }
|
||||||
|
.large-text { font-size: 1.3rem; }
|
||||||
|
|
||||||
|
.bold-text { font-weight: bolder; }
|
||||||
|
|
||||||
|
.block { display: block; }
|
||||||
|
.inline { display: inline; }
|
||||||
|
.inline.block { display: inline-block; }
|
||||||
|
|
||||||
|
.invisilink { text-decoration: none; color: inherit; }
|
||||||
|
.invisilist { list-style-type: none; margin: 5px; padding: 5px; }
|
||||||
|
|
||||||
|
.large-icon { max-width: 1.5em; max-height: 1.5em; vertical-align: middle; }
|
||||||
|
.tiny-image { max-width: 5em; max-height: 5em; }
|
||||||
|
.small-image { max-width: 10em; max-height: 10em; }
|
||||||
|
.medium-image { max-width: 20em; max-height: 20em; }
|
||||||
|
.large-image { max-width: 30em; max-height: 30emx; }
|
||||||
|
|
||||||
|
.img-text-middle{ vertical-align: middle; }
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
|
||||||
|
<path d="M4 0c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm0 1c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm-.5 1v2.22l.16.13.5.5.34.38.72-.72-.38-.34-.34-.34v-1.81h-1z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 272 B |
|
@ -62,13 +62,13 @@ module.exports = async function() {
|
||||||
let temp_image = item.content.match(/<img[^>]+?\bsrc=["']([^>]+?)["'][^>]+?\/?>/);
|
let temp_image = item.content.match(/<img[^>]+?\bsrc=["']([^>]+?)["'][^>]+?\/?>/);
|
||||||
if(temp_image !== null)
|
if(temp_image !== null)
|
||||||
item.media_image = temp_image[1];
|
item.media_image = temp_image[1];
|
||||||
console.log(temp_image);
|
|
||||||
}
|
}
|
||||||
console.log(`MEDIA IMAGE`, item.media_image);
|
console.log(`MEDIA IMAGE`, item.media_image);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
})));
|
})));
|
||||||
global.feed_items.sort((a, b) => b.pubdate_obj - a.pubdate_obj);
|
global.feed_items.sort((a, b) => b.pubdate_obj - a.pubdate_obj);
|
||||||
|
// console.log(feed_items.map(el => el.title));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -4,14 +4,17 @@
|
||||||
{% for post in pagination.items %}
|
{% for post in pagination.items %}
|
||||||
<article class="post">
|
<article class="post">
|
||||||
<h2><a href="{{ post.link }}">{{ post.title | striphtml }}</a></h2>
|
<h2><a href="{{ post.link }}">{{ post.title | striphtml }}</a></h2>
|
||||||
<img src="{% asset post.media_image %}" alt="">
|
<div class="post-image" style="background: url({% asset post.media_image %});"></div>
|
||||||
<div class="post-extract">
|
<div class="post-extract">
|
||||||
{{ post.description | striphtml }}…
|
{{ post.description | striphtml }}…
|
||||||
<span><a href="{{ post.link }}">Read more</a></span>
|
<div><a href="{{ post.link }}">Read more</a></div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="post-footer">
|
||||||
<span><a href="{{ post.parent.data.link | htmlentities }}"><img src="{{ post.author_image }}" alt="{{ post.author_name | htmlentities }} avatar" aria-hidden="true" /> {{ post.author_name | htmlentities }}</a></span>
|
<span><a href="{{ post.parent.data.link | htmlentities }}"><img class="large-icon" src="{{ post.author_image }}" alt="{{ post.author_name | htmlentities }} avatar" aria-hidden="true" /> {{ post.author_name | htmlentities }}</a></span>
|
||||||
<span><time datetime="{{ post.pubdate_iso }}">{{ post.pubdate_display | htmlentities }}</time></span>
|
<span>
|
||||||
|
<img class="large-icon open-iconic invert-when-dark" src="{% asset 'images/clock.svg' %}" alt="Clock icon" aria-hidden="hidden" />
|
||||||
|
<time datetime="{{ post.pubdate_iso }}">{{ post.pubdate_display | htmlentities }}</time>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
@ -19,16 +22,50 @@
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<nav>
|
<nav class="pagination">
|
||||||
<span>{% if page.url != pagination.href.first %}<a href="{{ pagination.href.first }}">First</a>{% else %}First{% endif %}</span>
|
<span>{% if page.url != pagination.href.first %}<a href="{{ pagination.href.first }}">First</a>{% else %}First{% endif %}</span>
|
||||||
|
|
||||||
<span>{% if pagination.href.previous %}<a href="{{ pagination.href.previous }}">Previous</a>{% else %}Previous{% endif %}</span>
|
<span>{% if pagination.href.previous %}<a href="{{ pagination.href.previous }}">Previous</a>{% else %}Previous{% endif %}</span>
|
||||||
|
|
||||||
{% for pageKey in pagination.pages %}
|
{% for pageKey in pagination.pages %}
|
||||||
<a href="{{ pagination.hrefs[ loop.index0 ] }}"{% if pagination.hrefs[ loop.index0 ] == page.url %} aria-current="page"{% endif %}>{{ loop.index }}</a>
|
<span><a href="{{ pagination.hrefs[ loop.index0 ] }}"{% if pagination.hrefs[ loop.index0 ] == page.url %} aria-current="page"{% endif %}>{{ loop.index }}</a></span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<span>{% if pagination.href.next %}<a href="{{ pagination.href.next }}">Next</a>{% else %}Next{% endif %}</span>
|
<span>{% if pagination.href.next %}<a href="{{ pagination.href.next }}">Next</a>{% else %}Next{% endif %}</span>
|
||||||
|
|
||||||
<span>{% if page.url != pagination.href.last %}<a href="{{ pagination.href.last }}">Last</a>{% else %}Last{% endif %}</span>
|
<span>{% if page.url != pagination.href.last %}<a href="{{ pagination.href.last }}">Last</a>{% else %}Last{% endif %}</span>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<script async defer>
|
||||||
|
/**
|
||||||
|
* Renders a given number of seconds as something that humans can understand more easily.
|
||||||
|
* @package core
|
||||||
|
* @param int seconds The number of seconds to render.
|
||||||
|
* @return string The rendered time.
|
||||||
|
*/
|
||||||
|
function human_time(seconds)
|
||||||
|
{
|
||||||
|
const tokens = [
|
||||||
|
{ unit: 31536000, text: 'year' },
|
||||||
|
{ unit: 2592000, text: 'month' },
|
||||||
|
{ unit: 604800, text: 'week' },
|
||||||
|
{ unit: 86400, text: 'day' },
|
||||||
|
{ unit: 3600, text: 'hour' },
|
||||||
|
{ unit: 60, text: 'minute' },
|
||||||
|
{ unit: 1, text: 'second' }
|
||||||
|
];
|
||||||
|
for (const { unit, text } of tokens) {
|
||||||
|
if (seconds < unit) continue;
|
||||||
|
let numberOfUnits = Math.floor(seconds / unit);
|
||||||
|
return `${numberOfUnits} ${text}${numberOfUnits>1?'s':''} ago`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("load", (event) => {
|
||||||
|
let els_time = document.querySelectorAll("time");
|
||||||
|
for(let i = 0; i < els_time.length; i++) {
|
||||||
|
let time_next = new Date(els_time[i].getAttribute("datetime"));
|
||||||
|
els_time[i].textContent = human_time((new Date() - time_next) / 1000);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue