1
0
mirror of https://github.com/kremalicious/blog.git synced 2024-11-23 10:27:20 +01:00
blog/gatsby-node.js

255 lines
5.7 KiB
JavaScript
Raw Normal View History

2018-07-17 23:33:55 +02:00
const path = require('path')
const { createFilePath } = require('gatsby-source-filesystem')
2018-09-07 13:08:01 +02:00
const fastExif = require('fast-exif')
2018-09-12 23:36:05 +02:00
const Fraction = require('fraction.js')
2018-09-14 00:35:40 +02:00
const dms2dec = require('dms2dec')
2018-09-30 03:11:08 +02:00
const { itemsPerPage } = require('./config')
2018-09-06 22:28:28 +02:00
2018-09-24 23:50:48 +02:00
const redirects = [
{ f: '/feed', t: '/feed.xml' },
{ f: '/feed/', t: '/feed.xml' }
]
2018-07-17 23:33:55 +02:00
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
2018-09-13 00:46:40 +02:00
// Markdown files
2018-07-17 23:33:55 +02:00
if (node.internal.type === 'MarkdownRemark') {
2018-09-13 00:46:40 +02:00
createMarkdownNodeFields(node, createNodeField, getNode)
}
// Image files
if (node.internal.mediaType === 'image/jpeg') {
readAndCreateExifFields(node, createNodeField)
}
}
2018-07-17 23:33:55 +02:00
2018-09-13 00:46:40 +02:00
// Create slug & date for posts from file path values
const createMarkdownNodeFields = (node, createNodeField, getNode) => {
const fileNode = getNode(node.parent)
const parsedFilePath = path.parse(fileNode.relativePath)
const slugOriginal = createFilePath({ node, getNode })
2018-07-17 23:33:55 +02:00
2018-09-13 00:46:40 +02:00
// slug
let slug
2018-07-17 23:33:55 +02:00
2018-09-13 00:46:40 +02:00
if (parsedFilePath.name === 'index') {
slug = `/${parsedFilePath.dir.substring(11)}` // remove date from file dir
} else {
slug = `/${slugOriginal.substring(12)}` // remove first slash & date from file path
2018-07-17 23:33:55 +02:00
}
2018-09-07 13:08:01 +02:00
2018-09-13 00:46:40 +02:00
createNodeField({
node,
name: 'slug',
value: slug
})
// date
let date
if (node.frontmatter.date) {
date = `${node.frontmatter.date}`
} else {
date = `${slugOriginal.substring(1, 10)}` // grab date from file path
2018-09-07 13:08:01 +02:00
}
2018-09-13 00:46:40 +02:00
createNodeField({
node,
name: 'date',
value: date
})
}
const readAndCreateExifFields = (node, createNodeField) => {
fastExif
.read(node.absolutePath, true)
.then(exifData => {
if (!exifData) return
createExifFields(exifData, createNodeField, node)
})
.catch(() => null) // just silently fail when exif can't be extracted
2018-07-17 23:33:55 +02:00
}
2018-09-13 00:46:40 +02:00
const createExifFields = (exifData, createNodeField, node) => {
2018-09-12 21:03:35 +02:00
const { Model } = exifData.image
const {
ISO,
FNumber,
ExposureTime,
FocalLength,
ExposureBiasValue
} = exifData.exif
2018-09-14 00:35:40 +02:00
const {
GPSLatitudeRef,
GPSLatitude,
GPSLongitudeRef,
GPSLongitude
} = exifData.gps
2018-09-12 21:03:35 +02:00
2018-09-12 23:36:05 +02:00
const { n, d } = new Fraction(ExposureTime)
2018-09-12 21:03:35 +02:00
const exposureShortened = parseFloat(ExposureBiasValue.toFixed(2))
2018-09-12 22:36:50 +02:00
const model = `${Model}`
2018-09-12 21:03:35 +02:00
const iso = `ISO ${ISO}`
const fstop = `ƒ ${FNumber}`
2018-09-12 23:36:05 +02:00
const shutterspeed = `${n}/${d}s`
2018-09-12 21:03:35 +02:00
const focalLength = `${FocalLength}mm`
2018-09-14 00:35:40 +02:00
const GPSdec = dms2dec(
GPSLatitude,
GPSLatitudeRef,
GPSLongitude,
GPSLongitudeRef
)
const latitude = GPSdec[0]
const longitude = GPSdec[1]
2018-09-12 21:03:35 +02:00
let exposure
if (ExposureBiasValue === 0) {
exposure = `+/- ${exposureShortened} ev`
} else if (ExposureBiasValue > 0) {
exposure = `+ ${exposureShortened} ev`
} else {
exposure = `${exposureShortened} ev`
}
2018-09-09 21:20:19 +02:00
// add exif fields to type File
createNodeField({
node,
name: 'exif',
value: {
iso,
model,
fstop,
shutterspeed,
focalLength,
2018-09-14 00:35:40 +02:00
exposure,
gps: {
latitude,
longitude
}
2018-09-09 21:20:19 +02:00
}
})
}
2018-07-17 23:33:55 +02:00
exports.createPages = ({ graphql, actions }) => {
2018-09-24 23:50:48 +02:00
const { createPage, createRedirect } = actions
2018-07-17 23:33:55 +02:00
return new Promise((resolve, reject) => {
resolve(
graphql(
`
{
2018-08-30 22:50:09 +02:00
allMarkdownRemark(sort: { fields: [fields___date], order: DESC }) {
2018-07-17 23:33:55 +02:00
edges {
node {
fields {
slug
2018-07-19 00:22:06 +02:00
date
2018-07-17 23:33:55 +02:00
}
2018-07-19 23:04:41 +02:00
frontmatter {
2018-08-30 22:50:09 +02:00
type
2018-07-19 23:04:41 +02:00
tags
}
2018-07-17 23:33:55 +02:00
}
}
}
}
`
).then(result => {
if (result.errors) {
/* eslint no-console: "off" */
console.log(result.errors)
reject(result.errors)
}
2018-07-19 00:22:06 +02:00
const posts = result.data.allMarkdownRemark.edges
2018-09-29 20:43:10 +02:00
const numPages = Math.ceil(posts.length / itemsPerPage)
2018-07-19 00:22:06 +02:00
2018-09-04 02:57:39 +02:00
// Generate posts & posts index
2018-09-29 20:43:10 +02:00
generateContent(createPage, posts, numPages)
2018-07-19 23:04:41 +02:00
2018-09-04 02:57:39 +02:00
// Generate Tag Pages
2018-09-29 20:43:10 +02:00
generateTagPages(createPage, posts, numPages)
2018-07-19 23:04:41 +02:00
2018-09-24 23:50:48 +02:00
// create manual redirects
redirects.forEach(({ f, t }) => {
createRedirect({
fromPath: f,
redirectInBrowser: true,
toPath: t
})
})
2018-07-17 23:33:55 +02:00
resolve()
})
)
})
}
2018-09-04 02:57:39 +02:00
2018-09-07 00:36:08 +02:00
const postsTemplate = path.resolve('src/templates/Posts.jsx')
2018-09-29 20:43:10 +02:00
const generateContent = (createPage, posts, numPages) => {
2018-09-04 02:57:39 +02:00
const postTemplate = path.resolve('src/templates/Post.jsx')
// Create Post pages
posts.forEach(post => {
createPage({
path: `${post.node.fields.slug}`,
component: postTemplate,
context: {
slug: post.node.fields.slug
}
})
})
2018-09-29 20:43:10 +02:00
// Create paginated Blog index pages
Array.from({ length: numPages }).forEach((_, i) => {
createPage({
path: i === 0 ? '/' : `/page/${i + 1}`,
component: postsTemplate,
context: {
limit: itemsPerPage,
skip: i * itemsPerPage,
numPages,
currentPageNumber: i + 1,
prevPage: i - 1,
nextPage: i + 2
}
})
2018-09-04 02:57:39 +02:00
})
}
2018-09-09 21:20:19 +02:00
const generateTagPages = (createPage, posts) => {
2018-09-29 20:43:10 +02:00
const tagList = arrayReducer(posts, 'tags')
2018-09-04 02:57:39 +02:00
tagList.forEach(tag => {
2018-09-13 21:51:13 +02:00
if (tag === 'goodies') return
2018-09-07 00:36:08 +02:00
// Create tag pages
2018-09-04 02:57:39 +02:00
createPage({
2018-09-29 20:43:10 +02:00
path: `/tags/${tag}/`,
2018-09-07 00:36:08 +02:00
component: postsTemplate,
2018-09-04 02:57:39 +02:00
context: { tag }
})
})
}
2018-09-29 20:43:10 +02:00
// https://www.adamjberkowitz.com/tags-and-categories-in-gatsby-js/
const arrayReducer = (postsArray, type) => {
return (postsArray = postsArray
.map(({ node }) => {
return node.frontmatter[type]
})
.reduce((a, b) => {
return a.concat(b)
}, [])
.filter((type, index, array) => {
return array.indexOf(type) === index
})
.sort())
}