parent
9420adb44a
commit
578cad3351
@ -0,0 +1,10 @@ |
||||
{% extends "gemini.njk" %}{% block content %}# {{ book.title }} |
||||
|
||||
{{ contents | safe }} |
||||
|
||||
({{ comment.size }} signes. Première publication {% if comment.issue %}sur {{ comment.medium | safe }} n°{{ comment.issue }}){% else %}le {{ comment.date.format('LL')}} sur {{ comment.medium | safe }}){% endif %} |
||||
|
||||
{% if comment.source %}=> {{ comment.source }} Document original{% endif %} |
||||
=> {{ filepath(comment.medium, ['/chroniques']) }} Toutes les chroniques sur {{ comment.medium | safe }} |
||||
=> /chroniques Toutes les chroniques |
||||
{% endblock %} |
@ -0,0 +1 @@ |
||||
{% block content %}{{ contents | safe }}{% endblock %} |
@ -0,0 +1,173 @@ |
||||
const config = require('./config.js') |
||||
const debug = require('debug')('gemini') |
||||
const Metalsmith = require('metalsmith') |
||||
const layouts = require('@metalsmith/layouts') |
||||
const moment = require('moment') |
||||
const path = require('path') |
||||
const slug = require('slug') |
||||
const statistics = require('./metalsmith-statistics-plugin') |
||||
|
||||
const __PROD__ = process.env.NODE_ENV === 'production' |
||||
|
||||
moment.locale('fr') |
||||
|
||||
function store (collection, key, value) { |
||||
if (collection[key] === undefined) { collection[key] = [] } |
||||
collection[key].push(value) |
||||
} |
||||
|
||||
function isGemText (filename) { |
||||
return /\.gmi$|\.gemini$/.test(path.extname(filename)) |
||||
} |
||||
|
||||
function filepath (filename, segments) { |
||||
const name = slug(filename, { mode: 'rfc3986' }) + '.gemini' |
||||
return path.join.apply(null, (segments || ['./']).concat([name])) |
||||
} |
||||
|
||||
function sortedComments (metalsmith, index) { |
||||
const sortedComments = {} |
||||
|
||||
metalsmith.metadata().comments.forEach(entry => { |
||||
if (index instanceof Function) { |
||||
store(sortedComments, index(entry.comment), entry) |
||||
} else { |
||||
store(sortedComments, entry.comment[index], entry) |
||||
} |
||||
}) |
||||
|
||||
return sortedComments |
||||
} |
||||
|
||||
function createIndex (files, filename, body) { |
||||
const entry = Object.assign({ |
||||
contents: Buffer.from(body) |
||||
}) |
||||
|
||||
files[filename] = entry |
||||
} |
||||
|
||||
function createCommentsIndex (index, entries) { |
||||
let body = '# ' + index + '\n\n' |
||||
|
||||
entries.forEach(entry => { |
||||
body += '=> /' + entry.filename + ' ' + entry.book.title + ', ' + entry.book.author |
||||
|
||||
if (index === entry.comment.medium) { |
||||
body += ' (' + entry.comment.date.year() + ')\n' |
||||
} else { |
||||
body += ' (sur ' + entry.comment.medium + ')\n' |
||||
body += entry.comment.excerpt |
||||
} |
||||
}) |
||||
|
||||
body += '\n=> /chroniques Retour à la liste complète\n' |
||||
|
||||
return body |
||||
} |
||||
|
||||
function rootIndexPlugin (files, metalsmith, done) { |
||||
let body = '# Chroniques\n' |
||||
|
||||
body += '\n## Par support\n\n' |
||||
Object.keys(sortedComments(metalsmith, 'medium')).forEach((medium) => { |
||||
body += '=> ' + filepath(medium, ['/chroniques']) + ' ' + medium + '\n' |
||||
}) |
||||
|
||||
body += '\n## Par année\n\n' |
||||
Object.keys(sortedComments(metalsmith, (c) => c.date.year())).forEach((year) => { |
||||
body += '=> /chroniques/' + year + ' ' + year + '\n' |
||||
}) |
||||
|
||||
createIndex(files, 'chroniques/index.gemini', body) |
||||
|
||||
done() |
||||
} |
||||
|
||||
function mediaIndexPlugin (files, metalsmith, done) { |
||||
Object.entries(sortedComments(metalsmith, 'medium')).forEach(([medium, comments]) => { |
||||
createIndex(files, filepath(medium, ['chroniques']), createCommentsIndex(medium, comments)) |
||||
}) |
||||
|
||||
done() |
||||
} |
||||
|
||||
function yearsIndexPlugin (files, metalsmith, done) { |
||||
Object.entries(sortedComments(metalsmith, (c) => c.date.year())).forEach(([year, comments]) => { |
||||
createIndex(files, filepath('index', ['chroniques', year]), createCommentsIndex(year, comments)) |
||||
}) |
||||
|
||||
done() |
||||
} |
||||
|
||||
function buildCommentsMetadata (files, metalsmith, done) { |
||||
const EXCERPT_MAX_LENGTH = 300 |
||||
|
||||
const comments = [] |
||||
|
||||
// TODO: The excerpt should take care of words boundaries
|
||||
const buildExcerpt = function (contents) { |
||||
let length = contents.indexOf('\n') |
||||
|
||||
if (length === -1) { |
||||
length = contents.length |
||||
} |
||||
|
||||
let excerpt = contents.substr(0, Math.min(length, EXCERPT_MAX_LENGTH)) |
||||
if (length > EXCERPT_MAX_LENGTH) { |
||||
excerpt += '…' |
||||
} |
||||
|
||||
return excerpt + '\n' |
||||
} |
||||
|
||||
Object.keys(files).forEach(filename => { |
||||
if (isGemText(filename)) { |
||||
const data = files[filename] |
||||
|
||||
if (data.comment !== undefined) { |
||||
data.comment.date = moment(data.comment.date) |
||||
data.comment.excerpt = buildExcerpt(data.contents.toString()) |
||||
data.comment.size = data.contents.length |
||||
data.layout = 'gemini-comment.njk' |
||||
|
||||
comments.push({ |
||||
book: data.book, |
||||
comment: data.comment, |
||||
filename |
||||
}) |
||||
} |
||||
} |
||||
}) |
||||
|
||||
debug('Identified %d comments: %s', comments.length) |
||||
|
||||
/* Comment are ordered by title by default. */ |
||||
comments.sort((a, b) => a.book.title.localeCompare(b.book.title)) |
||||
metalsmith.metadata().comments = comments |
||||
|
||||
done() |
||||
} |
||||
|
||||
module.exports = new Metalsmith(config.paths.projectRoot) |
||||
.clean(__PROD__) |
||||
.metadata({ |
||||
filepath |
||||
}) |
||||
.source(config.paths.geminiSource) |
||||
.destination(config.paths.geminiDestination) |
||||
.use(buildCommentsMetadata) |
||||
.use(rootIndexPlugin) |
||||
.use(mediaIndexPlugin) |
||||
.use(yearsIndexPlugin) |
||||
// TODO: atom.xml (et lien depuis l'index)
|
||||
.use(layouts({ |
||||
default: 'gemini.njk', |
||||
pattern: '**/*.gemini', |
||||
engineOptions: { |
||||
globals: { |
||||
production: __PROD__ |
||||
} |
||||
} |
||||
})) |
||||
.use(statistics()) |
Loading…
Reference in new issue