Compare commits

...

4 Commits

Author SHA1 Message Date
EpicKiwi f3cbc8e24b
Increased image size 2024-01-05 19:20:17 +01:00
EpicKiwi 7840029f8c
Added menu in header and homepage 2024-01-05 19:18:23 +01:00
EpicKiwi ae583c7bb7
Added responsiveness 2024-01-05 18:59:42 +01:00
EpicKiwi 026c439f02
Using JSONLD to bring data to main page 2024-01-05 18:10:23 +01:00
7 changed files with 6200 additions and 13 deletions

120
_src/js/data.js Normal file
View File

@ -0,0 +1,120 @@
import "../lib/jsonld.esm.js.js";
import jsonldRdfaParser from '../lib/jsonld8-rdfa.esm.js';
jsonld.registerRDFParser('text/html', jsonldRdfaParser);
export const GLOBAL_CONTEXT = {
"@vocab": "http://schema.org/",
"@language": "fr"
}
/**
* Fetch remote content data
* @param {String|URL} documentUrl Document URL to fetch
* @param {Object} context Optional context to format JSON
* @returns JSON-LD of data extracted from the provided page
*/
export async function fetchDocumentData(documentUrl, context = GLOBAL_CONTEXT){
let res = await fetch(documentUrl);
if(!res.ok)
throw new Error(`Network error ${res.status} ${res.statusText}`)
if(!res.headers.get("Content-Type").startsWith("text/html"))
throw new Error(`Invalid content type ${res.headers.get("Content-Type")}`)
let content = await res.text()
let remoteDoc = new DOMParser().parseFromString(content, "text/html");
let base = document.createElement("base")
base.href = documentUrl
remoteDoc.head.append(base)
return await getDocumentData(remoteDoc, context);
}
/**
* Extract data from a page document
* @param {Document} sourceDocument Page document to extract data from
* @param {Object} context Optional context to format JSON
* @returns JSON-LD of data extracted from the page
*/
export async function getDocumentData(sourceDocument = document, context = GLOBAL_CONTEXT) {
let resource = sourceDocument.body.getAttribute("resource")
if(resource)
resource = new URL(resource, sourceDocument.baseURI)
return await extractData(
sourceDocument.documentElement,
resource,
context
)
}
/**
* Get JSON data from a RDFa Formatted element
* @param {Element} sourceElement Source element to extract data from
* @param {Object} context Optional context to format JSON
* @returns JSON-LD of data extract from element
*/
export async function getData(sourceElement, context = GLOBAL_CONTEXT){
let resource = sourceElement.getAttribute("resource");
if(resource)
resource = new URL(resource, sourceElement.baseURI)
return await extractData(
sourceElement,
resource,
context
)
}
export function takeFirst(self){
if(!self){
return self
}
if(Array.isArray(self)){
return self[0]
} else {
return self
}
}
export function takeUrl(self){
if(!self){
return self
}
let first = takeFirst(self)
return first["@id"]
}
async function extractData(baseElement, rootId, context){
let sourceData = await jsonld.fromRDF(baseElement, {format: 'text/html'});
if(rootId) {
let frame = {
"@id": rootId
}
if(context) {
frame["@context"] = context
}
return await jsonld.frame(sourceData, frame)
} else if (context) {
return await jsonld.compact(sourceData, context)
} else {
return sourceData
}
}

View File

@ -7,6 +7,9 @@
header {
margin-bottom: 10vh;
display: flex;
justify-content: center;
align-items: stretch;
}
header h1 {
@ -14,6 +17,8 @@
font-family: "Degheest Director";
font-weight: 600;
flex: 1;
}
header h1 > a {
@ -33,13 +38,37 @@
header h1 small {
display: block;
}
nav li, nav li a {
color: #fff600;
text-decoration: none;
}
nav li a:hover {
text-decoration: underline;
}
nav ul {
list-style-type: none;
padding: none
}
nav {
text-align: right;
}
</style>
<header>
<h1><a href="/">
<img src="/_src/img/logo_kiosque.svg" alt="Logo du site" />
<span>Infokiosques du LOL <small>Brochures et autres textes</small></span>
<span>Infokiosque du LOL <small>Brochures et autres textes</small></span>
</a></h1>
<nav>
<ul>
<li><a href="https://labolyon.fr">Labolyon.fr</a></li>
<li><a href="https://wiki.labolyon.fr/doku.php?id=infokiosque">Wiki</a></li>
</ul>
</nav>
</header>
<slot></slot>

3413
_src/lib/jsonld.esm.js.js Normal file

File diff suppressed because one or more lines are too long

2435
_src/lib/jsonld8-rdfa.esm.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@ body > * {
h1 {
font-family: "Degheest Director";
font-weight: 700;
font-size: 3em;
font-size: min(3em, 10vw);
}
@media screen and (max-width: 500px) {
@ -103,9 +103,13 @@ ul li > a:first-child::before {
font-family: "Open Sans", sans-serif;
margin-left: -1.5ex;
margin-right: 0.5ex;
}
i, ul li > a:first-child::before {
font-size: 1.5em;
vertical-align: middle;
display: inline-block;
font-style: normal;
}
ul li > a:first-child:hover::before {
@ -113,6 +117,111 @@ ul li > a:first-child:hover::before {
transform: translateX(0.25ex);
}
#publications ul {
padding-left: 0;
}
#publications ul li > a:first-child::before {
content: unset;
}
#publications ul li > a {
text-decoration: none;
}
#publications .publication-card {
margin-bottom: 50px;
}
body > section {
margin-top: 10vh;
}
/* home */
.home > h1 {
text-align: center;
}
.home nav li a::before {
content: none;
}
.home nav ul {
padding: 0;
display: flex;
justify-content: center;
align-items: center;
gap: 5px;
}
.home nav li {
color: #fff600;
}
.home nav ul li:not(:last-child)::after {
content: "•";
margin-left: 5px;
}
/* publication card */
.publication-card {
display: grid;
grid-template-columns: 150px 1fr;
grid-template-rows: 1fr;
grid-auto-rows: min-content;
column-gap: 15px;
text-decoration: none !important;
width: 100%;
}
.publication-card > img:first-child {
grid-column: 1;
grid-row: 1 / 3;
width: 100%;
}
.publication-card h1 {
font-size: 1.5em;
margin: 0;
text-align: left;
}
.publication-card p {
margin: 0;
margin-top: 15px;
grid-column: 1 / 3;
}
.publication-card nav {
text-align: right;
margin-top: 15px;
grid-column: 1 / 3;
}
@media screen and (max-width: 500px) {
.publication-card {
grid-template-columns: 1fr;
}
.publication-card h1 {
font-size: 1.2em;
margin: 0;
}
.publication-card > img:first-child {
grid-column: 1;
grid-row: 1;
max-width: 150px;
margin-left: auto;
margin-right: auto;
margin-bottom: 15px;
}
.publication-card p, .publication-card nav {
grid-column: 1;
}
}

View File

@ -4,18 +4,26 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Infokiosques LOL</title>
<title>Infokiosque LOL</title>
<link rel="stylesheet" href="/_src/styles/global.css" />
</head>
<body vocab="http://schema.org/" typeof="Website" resource="." >
<body vocab="http://schema.org/" typeof="Website" resource="." class="home">
<img src="/_src/img/logo_kiosque.svg" alt="Logo du site" />
<h1 property="name">Inforkiosques du LOL <small>Brochures et autres textes</small></h1>
<h1 property="name">Infokiosque du LOL <small>Brochures et autres textes</small></h1>
<nav>
<ul>
<li><a href="https://labolyon.fr">Labolyon.fr</a></li>
<li><a href="https://wiki.labolyon.fr/doku.php?id=infokiosque">Wiki</a></li>
</ul>
</nav>
<section id="publications"
property="hasPart"
typeof="Collection"
resource="#publications" >
@ -28,14 +36,87 @@
</ul>
</section>
<section>
<h2>Resources</h2>
<template id="publication-card-tmplt">
<article class="publication-card">
<img property="image" src="" alt="Couverture" />
<h1 property="name"></h1>
<div class="meta">
<span>Par <span property="author"></span></span>
</div>
<p property="abstract"></p>
<nav>
<a href="" property="url">Plus d'infos <i>🠺</i></a>
</nav>
</article>
</template>
<ul>
<li><a href="https://labolyon.fr">labolyon.fr</a></li>
<li><a href="https://equa.space/notes/pdfjam/">using <code>pdfjam</code> for zine creation and bookbinding</a></li>
</ul>
</section>
<script type="module">
import {fetchDocumentData, takeFirst, takeUrl} from "/_src/js/data.js"
init()
async function init() {
for(let it of document.querySelectorAll("#publications ul > li a[href]")) {
let data = null;
try {
data = await fetchDocumentData(it.href)
} catch(e) {
continue;
}
let card = null;
try {
card = makePublicationCard(data)
} catch(e) {
continue;
}
it.innerHTML = ""
it.append(card)
}
}
function makePublicationCard(data){
let template = document.getElementById("publication-card-tmplt").content.cloneNode(true);
let root = template.children[0]
root.setAttribute("resource", takeFirst(data["@id"]))
root.setAttribute("typeof", takeFirst(data["@type"]))
let name = takeFirst(data.name)
if(name){
template.querySelector('[property="name"]').textContent = name
} else {
throw new Error("Provided data doesn't have a \"name\" field");
}
let author = takeFirst(data.author)
if(author){
template.querySelector('[property="author"]').textContent = author
} else {
template.querySelector('[property="author"]').parentElement.remove()
}
let abstract = takeFirst(data.abstract)
if(abstract){
template.querySelector('[property="abstract"]').textContent = abstract
} else {
template.querySelector('[property="abstract"]').remove()
}
let image = takeUrl(data.image)
if(image){
template.querySelector('[property="image"]').src = image
} else {
template.querySelector('[property="image"]').remove()
}
let url = takeUrl(data.url)
template.querySelector('[property="url"]').href = url || takeUrl(data)
return template
}
</script>
</body>
</html>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Détruire le capitalisme de surveillance — Cory Doctorow — Infokiosques LOL</title>
<title>Détruire le capitalisme de surveillance — Cory Doctorow — Infokiosque LOL</title>
<link rel="stylesheet" href="/_src/styles/global.css" />
<link rel="prefetch" href="/_src/js/layout.html" />
<script defer src="/_src/js/layout.js"></script>