Initial import.

This commit is contained in:
David Soulayrol 2022-06-27 22:02:17 +02:00
commit 1538631d84
54 changed files with 20025 additions and 0 deletions

20
scripts/config.js Normal file
View file

@ -0,0 +1,20 @@
const { resolve, join } = require('path')
const hostname = 'https://david.soulayrol.name'
const projectRoot = resolve(__dirname, '..')
const distribution = join(projectRoot, 'dist')
module.exports = {
hostname,
paths: {
projectRoot,
/* Nodes */
nodeModules: join(projectRoot, 'node_modules'),
/* Metalsmith */
metalsmithSource: 'content',
metalsmithDestination: distribution,
/* Server */
serverRoot: distribution
}
}

View file

@ -0,0 +1,108 @@
const path = require('path')
const Table = require('cli-table2')
const filesize = require('filesize')
function generateFileMap (files) {
return Object.keys(files).reduce((map, filename) => {
const file = files[filename]
const parsedFilename = path.parse(filename)
const ext = parsedFilename.ext.substr(1)
const extFiles = map[ext] || []
return {
...map,
[ext]: [
...extFiles,
{
file,
filename
}
]
}
}, {})
}
export function StatisticsPlugin (options) {
return (files, metalsmith, done) => {
const fileMap = generateFileMap(files)
const fileTypes = Object.keys(fileMap)
// File overview table
fileTypes.forEach((filetype) => {
const fileTypeFiles = fileMap[filetype]
const count = fileTypeFiles.length
const size = fileTypeFiles.reduce((totalsize, entry) => {
// Some plugins (eg. metalsmith-data-markdown) replace the Buffer by a string
if (typeof entry.file.contents === 'string') {
return totalsize + entry.file.contents.length
} else {
return totalsize + entry.file.contents.byteLength
}
}, 0)
const filenamesTable = new Table({
head: [`${count} ${filetype}-${count > 1 ? 'files' : 'file'} with total ${filesize(size)}`, 'File size'],
wordWrap: true,
colWidths: [process.stdout.columns - 16, 12]
})
fileTypeFiles.forEach((entry) => {
let size = 0
// Some plugins (eg. metalsmith-data-markdown) replace the Buffer by a string
if (typeof entry.file.contents === 'string') {
size = entry.file.contents.length
} else {
size = entry.file.contents.byteLength
}
filenamesTable.push([entry.filename, size])
})
console.log(filenamesTable.toString())
})
done()
}
}
export function DebugPlugin (options) {
function sanitizeTableContent (content) {
const length = content.length
content = content.replace(/\s+/g, ' ').slice(0, config.maxContentLength)
if (length > config.maxContentLength) {
content = content.trim() + '...'
}
return content
}
const defaultOptions = {
maxContentLength: 1000
}
const config = {
...defaultOptions,
...options
}
return (files, metalsmith, done) => {
const fileMap = generateFileMap(files)
const fileTypes = Object.keys(fileMap)
fileTypes.forEach((filetype) => {
const fileTypeFiles = fileMap[filetype]
fileTypeFiles.forEach((entry) => {
const content = sanitizeTableContent(entry.file.contents.toString())
const size = filesize(entry.file.contents.byteLength)
const metadata = {
...entry.file
}
delete metadata.contents
const fileTable = new Table({
head: [`${entry.filename} @ ${size}`],
wordWrap: true,
colWidths: [process.stdout.columns - 2]
})
fileTable.push([JSON.stringify(metadata, null, 2)])
fileTable.push([content])
console.log(fileTable.toString())
})
})
done()
}
}

View file

@ -0,0 +1,63 @@
const path = require('path')
const Table = require('cli-table2')
const filesize = require('filesize')
module.exports = plugin
function generateFileMap (files) {
return Object.keys(files).reduce((map, filename) => {
const file = files[filename]
const parsedFilename = path.parse(filename)
const ext = parsedFilename.ext.substr(1)
const extFiles = map[ext] || []
return {
...map,
[ext]: [
...extFiles,
{
file,
filename
}
]
}
}, {})
}
function plugin () {
return (files, metalsmith, done) => {
const fileMap = generateFileMap(files)
const fileTypes = Object.keys(fileMap)
// File overview table
fileTypes.forEach((filetype) => {
const fileTypeFiles = fileMap[filetype]
const count = fileTypeFiles.length
const size = fileTypeFiles.reduce((totalsize, entry) => {
// Some plugins (eg. metalsmith-data-markdown) replace the Buffer by a string
if (typeof entry.file.contents === 'string') {
return totalsize + entry.file.contents.length
} else {
return totalsize + entry.file.contents.byteLength
}
}, 0)
const filenamesTable = new Table({
head: [`${count} ${filetype}-${count > 1 ? 'files' : 'file'} with total ${filesize(size)}`, 'File size'],
wordWrap: true,
colWidths: [process.stdout.columns - 16, 12]
})
fileTypeFiles.forEach((entry) => {
let size = 0
// Some plugins (eg. metalsmith-data-markdown) replace the Buffer by a string
if (typeof entry.file.contents === 'string') {
size = entry.file.contents.length
} else {
size = entry.file.contents.byteLength
}
filenamesTable.push([entry.filename, size])
})
console.log(filenamesTable.toString())
})
done()
}
}

82
scripts/metalsmith.js Normal file
View file

@ -0,0 +1,82 @@
/* This is the actual metalsmith configuration script. */
const assets = require('metalsmith-assets')
const cleanCSS = require('metalsmith-clean-css')
const config = require('./config.js')
const groff = require('metalsmith-groff')
const layouts = require('@metalsmith/layouts')
const Metalsmith = require('metalsmith')
const markdown = require('metalsmith-markdownit')
const moment = require('moment')
const rename = require('metalsmith-rename')
const permalinks = require('@metalsmith/permalinks')
const sitemap = require('metalsmith-sitemap')
const slug = require('slug')
const statistics = require('./metalsmith-statistics-plugin')
const __PROD__ = process.env.NODE_ENV === 'production'
module.exports = new Metalsmith(config.paths.projectRoot)
.clean(__PROD__)
.metadata({
moment,
remove_diatrics: function (e) { return slug(e, { mode: 'rfc3986' }) },
site: {
title: 'David Soulayrol'
}
})
.source(config.paths.metalsmithSource)
.destination(config.paths.metalsmithDestination)
.use(cleanCSS({}))
.use(assets({
source: './assets/' + (process.env.NODE_ENV || 'dev'),
destination: './'
}))
.use(groff({
preprocessors: ['tbl'],
source: true
}))
.use(markdown({
html: true,
typographer: true,
quotes: ['«\xA0', '\xA0»', '\xA0', '\xA0'],
plugin: {
pattern: '**/*.md',
// fields: ['contents', 'excerpt']
extension: 'njk'
}
}))
.use(layouts({
default: 'default.njk',
pattern: '**/*.njk',
engineOptions: {
filters: {
setAttribute: (dictionary, key, value) => {
dictionary[key] = value
return dictionary
}
},
globals: {
production: __PROD__
}
}
}))
.use(rename([
[/\.njk$/, '.html']
]))
.use(permalinks({
pattern: 'documents/:title',
relative: 'folder',
// linksets: [
// {
// match: { path: 'blogposts' },
// pattern: 'blog/:date/:title',
// date: 'mmddyy'
// }
// ]
duplicatesFail: true
}))
.use(sitemap({
changefreq: 'yearly',
hostname: config.hostname
}))
.use(statistics())

71
scripts/run.js Normal file
View file

@ -0,0 +1,71 @@
const bs = require('browser-sync').create('Metalsmith')
const config = require('./config.js')
const debug = require('debug')('Run')
const metalsmith = require('./metalsmith')
const path = require('path')
const strip = require('strip-ansi')
function build (sync) {
debug('Building Metalsmith')
metalsmith.build((err) => {
if (err) {
debug('Metalsmith build error:')
debug(err)
if (sync) {
return bs.sockets.emit('fullscreen:message', {
title: 'Metalsmith Error:',
body: strip(`${err.message}\n\n${err.stack}`),
timeout: 100000
})
} else {
throw err
}
}
debug('Metalsmith build finished!')
if (sync) {
bs.reload()
}
})
}
function serve () {
bs.init({
server: config.paths.serverRoot,
port: 8080,
ui: {
port: 9000
},
open: false,
logLevel: 'debug',
logPrefix: 'BrowserSync',
logConnections: true,
logFileChanges: true,
notify: true,
files: [{
match: [
path.resolve(config.paths.projectRoot, 'content', '**', '*'),
path.resolve(config.paths.projectRoot, 'layouts', '**', '*.njk')
],
fn: function (event, file) {
build(true)
},
options: {
ignored: ['**/.#*', '**/*~', '**/#*#']
// /\.#|node_modules|~$/
}
}]
})
}
const args = process.argv.slice(2)
switch (args[0]) {
case 'build':
build()
break
case 'serve':
serve()
break
default:
console.log('Unknown arguments "' + args[0] + '"')
}