Wrangle up some CSS
parent
9dcee48717
commit
73a1576233
|
@ -32,13 +32,12 @@ async function filter_asset(src) {
|
|||
let type = await filetype.fromBuffer(content);
|
||||
if(typeof type === "undefined") {
|
||||
// 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
|
||||
if(match === null) match = [ null, "" ];
|
||||
type = { ext: match[1] }
|
||||
type = { ext: match[0] };
|
||||
}
|
||||
if(type.ext.length > 0) type.ext = `.${type.ext}`;
|
||||
|
||||
// It's a URL - download it
|
||||
filename = `${hash(src)}${type.ext}`;
|
||||
await fs.promises.writeFile(
|
||||
|
|
|
@ -37,23 +37,25 @@ description: "Hull Blogs provides aggregated content from University of Hull stu
|
|||
</a></h1>
|
||||
<p>{{ tagline }}</p>
|
||||
</header>
|
||||
<nav class="shadow-bottom">
|
||||
<nav>
|
||||
<ul>
|
||||
{% for navitem in collections.navigable %}
|
||||
<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>
|
||||
{% 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>
|
||||
</nav>
|
||||
|
||||
{{ content | safe }}
|
||||
<main>
|
||||
{{ content | safe }}
|
||||
</main>
|
||||
|
||||
<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>
|
||||
</footer>
|
||||
</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=["']([^>]+?)["'][^>]+?\/?>/);
|
||||
if(temp_image !== null)
|
||||
item.media_image = temp_image[1];
|
||||
console.log(temp_image);
|
||||
}
|
||||
console.log(`MEDIA IMAGE`, item.media_image);
|
||||
|
||||
return item;
|
||||
})));
|
||||
global.feed_items.sort((a, b) => b.pubdate_obj - a.pubdate_obj);
|
||||
// console.log(feed_items.map(el => el.title));
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -4,14 +4,17 @@
|
|||
{% for post in pagination.items %}
|
||||
<article class="post">
|
||||
<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">
|
||||
{{ post.description | striphtml }}…
|
||||
<span><a href="{{ post.link }}">Read more</a></span>
|
||||
<div><a href="{{ post.link }}">Read more</a></div>
|
||||
</div>
|
||||
<div>
|
||||
<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><time datetime="{{ post.pubdate_iso }}">{{ post.pubdate_display | htmlentities }}</time></span>
|
||||
<div class="post-footer">
|
||||
<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>
|
||||
<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>
|
||||
</article>
|
||||
|
||||
|
@ -19,16 +22,50 @@
|
|||
|
||||
</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 pagination.href.previous %}<a href="{{ pagination.href.previous }}">Previous</a>{% else %}Previous{% endif %}</span>
|
||||
|
||||
{% 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 %}
|
||||
|
||||
<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>
|
||||
</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