Ajout de la rubrique rencontres.

This commit is contained in:
David Soulayrol 2024-03-24 21:29:27 +01:00
parent 89223cbf2b
commit 179bb0a850
8 changed files with 157 additions and 12 deletions

View File

@ -9,13 +9,11 @@ Le site est créé à l'aide du logiciel libre [MetalSmith](http://www.metalsmit
### Préparation des sources
**Metalsmith** requiert la disponibilité de **NodeJS** et **npm**. L'installation de ces logiciels dépend du système d'exploitation utilisé.
Les sources peuvent être téléchargées depuis le dépôt **Gitea** ou bien copiées localement à l'aide de **git** avec la commande suivante.
Les sources du site peuvent être téléchargées depuis le dépôt **Gitea** ou bien copiées localement à l'aide de **git** avec la commande suivante.
git clone https://apps.ti-nuage.fr/gitea/ti-nuage/site.git
Le projet s'appuie sur un certain nombre de dépendances, utiles au développement ou à la génération du site lui-même. Pour installer ces dépendances :
Le projet s'appuie sur un certain nombre de dépendances, utiles au développement ou à la génération du site lui-même. Il est tout d'abord nécessaire d'installer **NodeJS** et **npm**. L'installation de ces logiciels dépend du système d'exploitation utilisé. Le reste des dépendances peut alors être assemblé avec la commande suivante.
npm install
@ -32,9 +30,17 @@ La liste des commandes existantes est disponible avec `npm run`. Il est possible
## Structure
Le site de l'association est essentiellement composé de pages statiques. Les billets d'actualité et les comptes-rendus de réunion sont eux-mêmes générés ou assemblés avec le reste des pages du site.
Sauf les exceptions détaillées plus bas, l'ensemble du site de l'association est composé de pages statiques dont les sources figurent dans ce projet. Les billets d'actualité et les comptes-rendus de réunion sont eux-mêmes générés ou assemblés avec le reste des pages du site.
Cependant, afin d'être réactif, l'affichage des événements du calendrier partagé de l'association est effectué depuis le navigateur. Si le navigateur dispose d'un support Javascript actif, alors :
### Supports de conférences
Les documents hébergés dans le projet [ti-nuage/talks](https://forge.ti-nuage.fr/gitea/ti-nuage/talks) peuvent être publiés sur la page /rencontres. Pour ce faire, il faut renseigner la variable d'environnement PATH_TALKS. Par exemple :
PATH_TALKS=../tinuage-talks/documents npm run server
### Intégration du calendrier
Afin d'être réactif, l'affichage des événements du calendrier partagé de l'association est effectué depuis le navigateur. Si le navigateur dispose d'un support Javascript actif, alors :
- les événements à venir sont mixés avec les billets récents du blog dans la rubrique Actualité de la page d'accueil ;
- le menu propose une entrée « Calendrier » à la suite de « Actualité ». Cette nouvelle page présente plus largement les événements récents ou à venir.

View File

@ -0,0 +1,7 @@
---
permalink: false
title: Rencontres
---
Outre l'accueil offert par l'association le premier jeudi de chaque mois, Ti Nuage va aussi à la rencontre d'autres lieux pour présenter et discuter les thèmes qui lui sont chers : la liberté de l'utilisateur de services numériques et la protection de ses données.
Voici les documents utilisés comme support lors des rencontres, conférences et autres causeries faites par l'association. Tous sont disponibles selon la licence [CC-BY-SA version 2.0 ou ultérieure](https://creativecommons.org/licenses/by-sa/2.0/fr/). Leurs fichiers sources sont disponibles sur notre [forge logicielle](https://forge.ti-nuage.fr/gitea/ti-nuage/talks).

View File

@ -21,6 +21,7 @@
<ul id="menu-association">
<li><a href="/association.html">Découvrir l'association</a></li>
<li><a href="/blog">Actualités</a></li>
<li><a href="/rencontres">Rencontres</a></li>
</ul>
</section>
<section>

View File

@ -6,9 +6,9 @@
"main": "",
"scripts": {
"build": "npm run clean && npm run build:metalsmith",
"build:prod": "NODE_ENV=production npm run build",
"build:metalsmith": "node scripts/run.js build",
"clean": "rimraf dist",
"build:prod": "NODE_ENV=production npm run build",
"clean": "rimraf dist && rm -rf content/talks",
"dev": "npm run build && nodemon scripts/run.js serve",
"server": "npm run build && http-server dist",
"deploy": "npm run build:prod && cd dist && rsync -v -rlptz --relative -e \"ssh -p $SERVER_PORT\" ./ $SERVER_PATH",

View File

@ -9,6 +9,7 @@ module.exports = {
hostname,
paths: {
projectRoot,
talksRoot: process.env.PATH_TALKS,
/* Nodes */
leaflet: join(projectRoot, 'node_modules', 'leaflet', 'dist'),
/* Metalsmith */

View File

@ -10,10 +10,9 @@ function plugin (options) {
return function (files, metalsmith, done) {
const dest = options.destination
const items = options.files.length
const promises = []
const addTask = function (promise) {
const addTask = function (items, promise) {
promises.push(promise)
if (items === promises.length) {
debug('Waiting for ' + items + 'copy operations.')
@ -27,8 +26,19 @@ function plugin (options) {
}
}
options.files.forEach((filename) => {
addTask(new Promise(function (resolve, reject) {
const iterateFiles = function (options, action) {
if (options.files != null) {
options.files.forEach((filename) => action(filename, options.files.length))
}
if (options.generator != null) {
options.generator(documents => {
documents.forEach((filename) => action(filename, documents.length))
})
}
}
iterateFiles(options, (filename, items) => {
addTask(items, new Promise(function (resolve, reject) {
fs.stat(filename, function (err, stats) {
if (err) return reject(err)
fs.readFile(filename, function (err, buffer) {

View File

@ -0,0 +1,97 @@
const { Buffer } = require('node:buffer')
const config = require('./config.js')
const debug = require('debug')('metalsmith-tinuage-talks')
const path = require('path')
module.exports = plugin
/**
* Un plugin pour Metalsmith qui lit une collection de fichiers PDF la section
* rencontres du site.
*
* @return {Function}
*/
function plugin () {
const IndexCreator = {
setup: function (page) {
this.page = page
this.talks = []
},
add: function (filename) {
const basename = path.basename(filename)
const names = basename.substring(0, basename.lastIndexOf('.')).split('__')
if (names.length >= 2) {
const name = names[0].replaceAll('_', ' ')
const location = names[1].substring(0, names[1].lastIndexOf('_')).replaceAll('_', ' ')
const year = names[1].substring(names[1].lastIndexOf('_') + 1)
const talk = this.getEntry(year, location, name)
if (names.length === 3 && names[2] === ('notes')) {
talk.notes = filename
} else {
talk.doc = filename
}
} else {
console.log('Ignoring talk ' + filename)
}
},
fill: function (files) {
let html = ''
this.talks
.reduce(
(map, talk) => {
(map.get(talk.year) || map.set(talk.year, []).get(talk.year)).push(talk)
return map
},
new Map())
.forEach((talks, year) => {
html += '<h2>' + year + '</h2>\n'
talks
.sort((a, b) => a.year - b.year || a.title - b.title)
.forEach(talk => {
html += '<p>' + talk.title + ', ' + talk.location + '&nbsp;: <a href="/' + talk.doc + '">Présentation</a>, <a href="/' + talk.notes + '">Notes</a></p>\n'
})
})
this.page.contents = Buffer.concat([
this.page.contents,
Buffer.from(html)
])
},
getEntry: function (year, location, title) {
let talk = this.talks.find(t => t.year === year && t.location === location && t.title === title)
if (talk == null) {
talk = { location, title, year }
this.talks.push(talk)
}
return talk
}
}
return function (files, metalsmith, done) {
if (config.paths.talksRoot) {
const creator = Object.create(IndexCreator)
creator.setup(files['rencontres/index.html'])
Object.keys(files).forEach(filename => {
if (/^rencontres\/.*\.pdf$/.test(filename)) {
debug('Handling', filename)
creator.add(filename)
}
})
creator.fill()
}
done()
}
}

View File

@ -7,6 +7,7 @@ const config = require('./config.js')
const collections = require('@metalsmith/collections')
const copy = require('./metalsmith-copy')
const excerpts = require('@metalsmith/excerpts')
const fs = require('node:fs')
const groff = require('metalsmith-groff')
const layouts = require('@metalsmith/layouts')
const Metalsmith = require('metalsmith')
@ -15,6 +16,7 @@ const marked = require('marked')
const permalinks = require('@metalsmith/permalinks')
const rename = require('metalsmith-rename')
const services = require('./metalsmith-tinuage-services')
const talks = require('./metalsmith-tinuage-talks')
const sitemap = require('metalsmith-sitemap')
const slug = require('slug')
const statistics = require('./metalsmith-statistics-plugin')
@ -77,6 +79,26 @@ module.exports = new Metalsmith(config.paths.projectRoot)
files: [join(config.paths.leaflet, 'leaflet.css')],
destination: './css'
}))
.use(copy({
generator: (callback) => {
if (config.paths.talksRoot != null) {
return fs.readdir(config.paths.talksRoot, (err, filenames) => {
let documents = []
if (err) {
console.error('%s: %s', config.paths.talksRoot, err)
} else {
documents = filenames
.filter(f => { return f.indexOf('.pdf') !== -1 })
.map(f => { return join(config.paths.talksRoot, f) })
}
callback(documents)
})
}
},
destination: './rencontres'
}))
.use(copy({
files: [
join(config.paths.leaflet, 'images', 'marker-icon.png'),
@ -106,6 +128,7 @@ module.exports = new Metalsmith(config.paths.projectRoot)
}))
.use(chatons())
.use(services())
.use(talks())
.use(excerpts())
.use(permalinks({
pattern: 'blog/:date/:title',