1
0
Fork 0

new photos

This commit is contained in:
Matthias Kretschmann 2019-10-05 00:30:38 +02:00
parent f0bd16ec65
commit 974f6d860c
Signed by: m
GPG Key ID: 606EEEF3C479A91F
17 changed files with 117 additions and 16 deletions

View File

@ -220,13 +220,15 @@ npm run new "Hello World"
npm run new "Hello World" 2017-12-27
```
Create a new photo post with date, title & description pre-filled from EXIF/IPTC data of a given image file:
```bash
npm run new "Hello World" photo
npm run new "Hello World" photo 2017-12-27
npm run new photo /path/to/photo.jpg
```
- [`scripts/new.js`](scripts/new.js)
- [`scripts/new.md`](scripts/new.md)
- [`scripts/new-photo.md`](scripts/new-photo.md)
## 🚚 Deployment

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -0,0 +1,9 @@
---
type: photo
date: 2019-01-27T00:00:00.000Z
title: All Work And No Play
image: 2019-01-27-all-work-and-no-play.jpg
---
Inside the [“Stanley Kubrick” exhibition](https://www.cccb.org/en/exhibitions/file/stanley-kubrick/228237) in the [Centre de Cultura Contemporània de Barcelona (CCCB)](https://www.cccb.org) in Barcelona, Catalonia, Spain.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

View File

@ -0,0 +1,9 @@
---
type: photo
date: 2019-02-25T22:51:00.000Z
title: Edifício Itália
image: 2019-02-25-edificio-italia.jpg
---
View over São Paulo from the 46th floor of Edifício Itália.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@ -0,0 +1,9 @@
---
type: photo
date: 2019-03-06T17:52:46.000Z
title: Brazilian Museum of Sculpture and Ecology
image: 2019-03-06-brazilian-museum-of-sculpture-and-ecology.jpg
---
On the grounds of the Brazilian Museum of Sculpture and Ecology (MuBE) in São Paulo, Brazil.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

View File

@ -0,0 +1,9 @@
---
type: photo
date: 2019-03-13T00:00:00.000Z
title: Paraty-Mirim
image: 2019-03-13-paraty-mirim.jpg
---
At the Paraty-Mirim beach in Paraty, Rio de Janeiro, Brazil.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

View File

@ -0,0 +1,9 @@
---
type: photo
date: 2019-09-29T13:57:00.000Z
title: Arco di Costantino
image: 2019-09-29-arco-di-costantino.jpg
---
The Arch of Constantine seen through the Collosseum walls in Rome, Italy.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

View File

@ -0,0 +1,9 @@
---
type: photo
date: 2019-09-29T15:31:00.000Z
title: Foro di Cesare
image: 2019-09-29-foro-di-cesare.jpg
---
View over the [Forum of Caesar](https://en.wikipedia.org/wiki/Forum_of_Caesar) within the [Imperial Forum](https://en.wikipedia.org/wiki/Imperial_fora) in Rome, Italy.

View File

@ -54,6 +54,7 @@ const constructExifFields = (exifData, createNodeField, node) => {
FNumber,
ExposureTime,
FocalLength,
FocalLengthIn35mmFormat,
ExposureBiasValue,
ExposureMode,
LensModel
@ -61,7 +62,7 @@ const constructExifFields = (exifData, createNodeField, node) => {
const iso = `ISO ${ISO}`
const fstop = `ƒ ${FNumber}`
const focalLength = `${FocalLength}mm`
const focalLength = `${FocalLengthIn35mmFormat || FocalLength}mm`
// Shutter speed
const { n, d } = new Fraction(ExposureTime)

View File

@ -112,6 +112,7 @@
"identity-obj-proxy": "^3.0.0",
"jest": "^24.9.0",
"markdownlint-cli": "^0.18.0",
"node-iptc": "^1.0.5",
"node-sass": "^4.12.0",
"npm-run-all": "^4.1.5",
"ora": "^4.0.0",

View File

@ -6,4 +6,4 @@ title: TITLE
image: DATE_SHORT-SLUG.jpg
---
Beep Boop.
DESCRIPTION

View File

@ -2,6 +2,8 @@ import fs from 'fs-extra'
import path from 'path'
import slugify from 'slugify'
import ora from 'ora'
import fastExif from 'fast-exif'
import iptc from 'node-iptc'
const templatePath = path.join(__dirname, 'new.md')
const templatePathPhoto = path.join(__dirname, 'new-photo.md')
@ -14,24 +16,55 @@ if (!process.argv[2]) {
spinner.fail('Use the format `npm run new "Title of post"`')
}
const title = process.argv[2]
const isPhoto = process.argv[3] === 'photo'
let title = process.argv[2]
const isPhoto = process.argv[2] === 'photo'
spinner.text = `Adding '${title}'.`
const titleSlug = slugify(title, { lower: true })
let titleSlug = slugify(title, { lower: true })
const postsPath = path.join('.', 'content', 'posts')
const photosPath = path.join('.', 'content', 'photos')
let date = new Date().toISOString()
if (isPhoto) {
if (process.argv[4]) {
date = new Date(process.argv[4]).toISOString()
async function getIptc(imagePath) {
return new Promise((resolve, reject) => {
fs.readFile(imagePath, (err, data) => {
if (err) reject(err)
const iptcData = iptc(data)
return resolve(iptcData)
})
})
}
async function getExif(imagePath) {
let exifData
try {
exifData = await fastExif.read(imagePath, true)
} catch (error) {
return null
}
let iptcData
try {
iptcData = await getIptc(imagePath)
} catch (error) {
return null
}
return { ...exifData, iptc: { ...iptcData } }
}
async function createPhotoPost() {
const photo = process.argv[3]
const exifData = await getExif(photo)
title = exifData.iptc.object_name || exifData.iptc.title
titleSlug = slugify(title, { lower: true })
date = new Date(exifData.exif.DateTimeOriginal).toISOString()
const dateShort = date.slice(0, 10)
const filePhoto = `${photosPath}/${dateShort}-${titleSlug}.md`
const description = exifData.iptc.caption
const fileName = `${dateShort}-${titleSlug}`
const postPhoto = `${photosPath}/${fileName}.md`
const newContentsPhoto = templatePhoto
.split('TITLE')
@ -42,13 +75,23 @@ if (isPhoto) {
.join(date)
.split('DATE_SHORT')
.join(dateShort)
.split('DESCRIPTION')
.join(description)
fs.appendFile(filePhoto, newContentsPhoto, err => {
if (err) spinner.fail(`Error creating photo post: ${err}`)
spinner.succeed(
`New photo post '${title}' created.\n\n Use ${dateShort}-${titleSlug}.jpg as the photo file name.`
)
// copy photo file in place
fs.copyFile(photo, `${photosPath}/${fileName}.jpg`, err => {
if (err) spinner.fail(`Error copying photo file: ${err}`)
})
// create photo post file
fs.appendFile(postPhoto, newContentsPhoto, err => {
if (err) spinner.fail(`Error creating photo post: ${err}`)
spinner.succeed(`New photo post '${title}' as '${fileName}.md' created.`)
})
}
if (isPhoto) {
createPhotoPost()
} else {
if (process.argv[3]) {
date = new Date(process.argv[3]).toISOString()