\n'
statistics += ' Statistics
\n'
const commitStats = changedLines(commits)
const contributors = uniqueContributors(commits)
statistics += ` In the month of ${months[wantedMonth]}, `
statistics += `${commits.length} commits were made by ${contributors.length} contributors, `
statistics += `changing a total of ${Math.abs(commitStats.total)} (+${commitStats.added}|-${commitStats.deleted}) lines. `
statistics += `${opened.length} issues were opened and `
statistics += `${closed.length} issues were closed.
\n`
statistics += ` An average of ${(opened.length / 30).toFixed(2)} issues were opened `
statistics += `and ${(closed.length / 30).toFixed(2)} issues were closed each day.
\n`
statistics += ` The average time to close issues was ${avgTime(closed, 'days')} days `
statistics += `or ${avgTime(closed, 'hours')} hours.
\n`
const topUsers = freqUsers(opened, 3)
statistics += ' Top 3 issue creators:
\n'
statistics += ' \n'
for (const user in topUsers) {
statistics += ' - \n'
statistics += ` ${user}`
statistics += ' with '
statistics += `${topUsers[user]} issues created.\n`
statistics += '
\n'
}
statistics += '
\n'
let labels = labelsAlphabet(opened, true)
statistics += ' Amount of labels assigned to currently open issues:
\n'
statistics += ' \n'
for (const label in labels) {
statistics += ' - \n'
statistics += ` ${label}:`
statistics += `${labels[label]} `
if (labels[label] === 1) statistics += 'time.\n'
else statistics += 'times.\n'
statistics += '
\n'
}
statistics += '
\n'
labels = labelsAlphabet(closed, false)
statistics += ' Amount of labels assigned to closed issues:
\n'
statistics += ' \n'
for (const label in labels) {
statistics += ' - \n'
statistics += ` ${label}:`
statistics += `${labels[label]} `
if (labels[label] === 1) statistics += 'time.\n'
else statistics += 'times.\n'
statistics += '
\n'
}
statistics += '
\n'
statistics += '\n'
fs.writeFileSync(outIssuesPath + '_statistics.html', statistics, { encoding: 'UTF-8' })
resolve()
})
}
function createFeeds() {
const feed = new Feed({
title: 'Tildes Issue Log',
description: 'Monthly blog highlighting the changes of Tildes.net',
id: 'https://til.bauke.xyz',
link: 'https://til.bauke.xyz',
language: 'en',
image: 'https://til.bauke.xyz/android-chrome-192x192.png',
favicon: 'https://til.bauke.xyz/favicon.ico',
copyright: 'AGPL-3.0-or-later Tildes Issue Log Contributors https://gitlab.com/Bauke/tildes-issue-log',
generator: 'https://github.com/jpmonette/feed',
feedLinks: {
atom: 'https://til.bauke.xyz/feed.atom',
json: 'https://til.bauke.xyz/feed.json',
rss: 'https://til.bauke.xyz/feed.rss',
},
author: {
name: 'Bauke',
email: 'me@bauke.xyz',
link: 'https://bauke.xyz',
},
})
const posts = fs.readdirSync(path.join(paths.out, 'posts'))
// Sort the posts descending year and month
posts.sort((a, b) => {
const yearA = Number(a.replace(/\D/g, ''))
const yearB = Number(b.replace(/\D/g, ''))
if (yearA === yearB) {
const monthA = months.join(',').toLowerCase().split(',').indexOf(a.substring(0, a.indexOf('-'))) + 1
const monthB = months.join(',').toLowerCase().split(',').indexOf(b.substring(0, b.indexOf('-'))) + 1
return monthB - monthA
}
return yearB - yearA
})
for (const post of posts) {
// Skip the template, that doesn't need to be included
if (post.includes('template')) {
continue
}
const html = fs.readFileSync(path.join(paths.out, 'posts', post), 'UTF8')
const $ = cheerio.load(html)
const title = $('#wrapper>h1').text()
const id = `https://til.bauke.xyz/posts/${post}`
const date = new Date(Date.UTC(
Number(post.replace(/\D/g, '')),
// Add one to the month since UTC months are 0 based and since we set the
// day as 0 we'll get the Date back as the last day of the previous month
months.join(',').toLowerCase().split(',').indexOf(post.substring(0, post.indexOf('-'))) + 1,
0, 23, 59, 59
))
const content = $('#post')
.html()
.replace(/