kremalicious/blog

View on GitHub
scripts/new/createPhotoPost.ts

Summary

Maintainability
A
0 mins
Test Coverage
A
93%
import { promises as fs, existsSync, mkdirSync, readFileSync } from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import type { Ora } from 'ora'
import { readOutExif } from '../../src/lib/exif/readOutExif.js'
import { slugify } from '../../src/lib/slugify/slugify.js'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const templatePathPhoto = path.join(__dirname, 'new-photo.md')

export async function createPhotoPost(
  dest: string,
  spinner: Ora,
  photo: string,
  photoTitle?: string
) {
  let title: string | undefined
  let titleSlug: string
  let date: string
  let postPhotoFile = ''

  try {
    const templatePhoto = readFileSync(templatePathPhoto).toString()
    const exifData = await readOutExif(photo)
    if (!exifData) throw new Error('No exif data found in image')
    const { iptc, exif } = exifData

    title = iptc?.object_name || iptc?.caption || photoTitle
    if (!title)
      throw new Error(
        'No title given. Add to IPTC, or use the format `npm run new photo path/to/photo.jpg "Title of post"'
      )
    spinner.text = `Adding '${title}'.`

    titleSlug = slugify(title)
    date = new Date(exif?.date).toISOString()
    const dateShort = date.slice(0, 10)
    const description = iptc?.caption
    const keywords = (iptc?.keywords as string[])?.join('\n  - ')
    const folderName = `${dateShort}-${titleSlug}`
    const destination = `${dest}/${folderName}`
    postPhotoFile = `${destination}/index.md`

    const newContentsPhoto = templatePhoto
      .split('TITLE')
      .join(title)
      .split('SLUG')
      .join(titleSlug)
      .split('DATE_LONG')
      .join(date)
      .split('DATE_SHORT')
      .join(dateShort)
      .split('DESCRIPTION')
      .join(description)
      .split('TAGS')
      .join(keywords)

    // Create the destination folder if it doesn't exist
    if (!existsSync(destination)) {
      mkdirSync(destination, { recursive: true })
    }

    // copy photo file in place
    await fs.copyFile(photo, `${destination}/${folderName}.jpg`)

    // create photo post file
    await fs.appendFile(postPhotoFile, newContentsPhoto)
    spinner.succeed(
      `New photo post '${title}' under '${postPhotoFile}' created.`
    )
  } catch (error: unknown) {
    spinner.fail((error as Error).message)
  }

  return postPhotoFile
}