diff --git a/.config/astro.config.ts b/.config/astro.config.ts index 870c1479..9e35d2a8 100644 --- a/.config/astro.config.ts +++ b/.config/astro.config.ts @@ -1,6 +1,6 @@ import { defineConfig } from 'astro/config' -import remarkLeadParagraph from '../src/lib/remark-lead-paragraph' -import remarkToc from '../src/lib/remark-toc' +import { remarkLeadParagraph } from '../src/lib/remark-lead-paragraph/remark-lead-paragraph' +import { remarkToc } from '../src/lib/remark-toc/remark-toc' import react from '@astrojs/react' import sitemap from '@astrojs/sitemap' import expressiveCode from 'astro-expressive-code' diff --git a/scripts/new/createArticlePost.ts b/scripts/new/createArticlePost.ts index 74c4be75..dd06360c 100644 --- a/scripts/new/createArticlePost.ts +++ b/scripts/new/createArticlePost.ts @@ -2,7 +2,7 @@ import fs from 'node:fs/promises' import { existsSync, mkdirSync, readFileSync } from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' -import slugify from '../../src/lib/slugify.js' +import { slugify } from '../../src/lib/slugify' import type { Ora } from 'ora' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/scripts/new/createPhotoPost.ts b/scripts/new/createPhotoPost.ts index e2d8c3fc..cc425975 100644 --- a/scripts/new/createPhotoPost.ts +++ b/scripts/new/createPhotoPost.ts @@ -1,7 +1,7 @@ import fs from 'node:fs/promises' import { existsSync, mkdirSync, readFileSync } from 'node:fs' -import slugify from '../../src/lib/slugify.js' -import { readOutExif } from '../../src/lib/exif/index.js' +import { slugify } from '../../src/lib/slugify' +import { readOutExif } from '@lib/exif' import path from 'node:path' import { fileURLToPath } from 'node:url' import type { Ora } from 'ora' diff --git a/src/components/Exif/index.astro b/src/components/Exif/index.astro index 66399e04..7c67dad5 100644 --- a/src/components/Exif/index.astro +++ b/src/components/Exif/index.astro @@ -1,5 +1,5 @@ --- -import type { Exif } from '@lib/exif/types' +import type { Exif } from '@lib/exif' import { Camera, Crosshair, diff --git a/src/components/layouts/Post/Meta.astro b/src/components/layouts/Post/Meta.astro index 519ad5f4..b7d026c6 100644 --- a/src/components/layouts/Post/Meta.astro +++ b/src/components/layouts/Post/Meta.astro @@ -1,6 +1,6 @@ --- import type { CollectionEntry } from 'astro:content' -import slugify from '@lib/slugify' +import { slugify } from '@lib/slugify' import config from '@config/blog.config' import Tag from '@components/Tag.astro' import styles from './Meta.module.css' diff --git a/src/lib/astro/index.ts b/src/lib/astro/index.ts index c3ba9f5a..7e1e9101 100644 --- a/src/lib/astro/index.ts +++ b/src/lib/astro/index.ts @@ -1,6 +1,7 @@ -export { getAllPosts } from './getAllPosts' -export { getAllTags } from './getAllTags' -export { getPostsByTag } from './getPostsByTag' -export { loadAndFormatCollection } from './loadAndFormatCollection' -export { sortPosts } from './sortPosts' -export { getAllPostsForSearch } from './getAllPostsForSearch' +export * from './getAllPosts' +export * from './getAllTags' +export * from './getPostsByTag' +export * from './getSlug' +export * from './loadAndFormatCollection' +export * from './sortPosts' +export * from './getAllPostsForSearch' diff --git a/src/lib/exif/format.test.ts b/src/lib/exif/format.test.ts new file mode 100644 index 00000000..759593c3 --- /dev/null +++ b/src/lib/exif/format.test.ts @@ -0,0 +1,78 @@ +import { it, describe, expect } from 'vitest' +import { formatGps, formatExposure, formatExif } from './format' +import type { FastExif } from '.' + +describe('Exif formatting functions', () => { + describe('formatGps', () => { + it('should format GPS data correctly', () => { + const input: FastExif['gps'] = { + GPSLatitudeRef: 'N', + GPSLatitude: [52, 30, 0], + GPSLongitudeRef: 'E', + GPSLongitude: [13, 23, 0] + } + const result = formatGps(input) + expect(result).toEqual({ + latitude: 52.5, + longitude: 13.383333333333333 + }) + }) + }) + + describe('formatExposure', () => { + it('should format exposure correctly for positive numbers', () => { + const input = 0.25 + const result = formatExposure(input) + expect(result).toBe('+ 0.25 ev') + }) + + it('should format exposure correctly for negative numbers', () => { + const input = -0.25 + const result = formatExposure(input) + expect(result).toBe('- 0.25 ev') + }) + }) + + describe('formatExif', () => { + it('should format EXIF data correctly', () => { + const input: FastExif = { + image: { Model: 'FC7203' }, + exif: { + ISO: 100, + FNumber: 2.8, + ExposureTime: 1 / 50, + FocalLength: 24, + ExposureBiasValue: 0, + DateTimeOriginal: '2020-12-31T23:59:59.000Z' + }, + gps: { + GPSLatitudeRef: 'N', + GPSLatitude: [52, 30, 0], + GPSLongitudeRef: 'E', + GPSLongitude: [13, 23, 0] + } + } + const result = formatExif(input) + expect(result).toEqual({ + date: expect.any(String), + iso: 'ISO 100', + model: 'DJI Mavic Mini', + fstop: 'ƒ/2.8', + shutterspeed: '1/50s', + focalLength: '24mm', + lensModel: undefined, + exposure: '+/- 0 ev', + gps: { + latitude: 52.5, + longitude: 13.383333333333333 + } + }) + }) + + it('returns nothing when no exif received', () => { + const input: FastExif = {} + const result = formatExif(input) + expect(result).toBeUndefined() + }) + }) +}) diff --git a/src/lib/exif/format.ts b/src/lib/exif/format.ts index 10e7c180..c0ba7289 100644 --- a/src/lib/exif/format.ts +++ b/src/lib/exif/format.ts @@ -5,7 +5,7 @@ import getCoordinates from 'dms2dec' import Fraction from 'fraction.js' import type { ExifFormatted, FastExif } from './types.ts' -function formatGps(gpsData: FastExif['gps']): { +export function formatGps(gpsData: FastExif['gps']): { latitude: number longitude: number } { @@ -24,18 +24,16 @@ function formatGps(gpsData: FastExif['gps']): { return { latitude, longitude } } -function formatExposure(exposureMode: number) { - if (exposureMode === null || exposureMode === undefined) return +export function formatExposure(exposureMode: number) { + if (!exposureMode || exposureMode === 0) return `+/- 0 ev` const exposureShortened = parseFloat(exposureMode.toFixed(2)) let exposure - if (exposureMode === 0) { - exposure = `+/- ${exposureShortened} ev` - } else if (exposureMode > 0) { + if (exposureMode > 0) { exposure = `+ ${exposureShortened} ev` } else { - exposure = `${exposureShortened} ev` + exposure = `- ${Math.abs(exposureShortened)} ev` } return exposure @@ -76,12 +74,12 @@ export function formatExif(exifData: FastExif): ExifFormatted | undefined { const exposure = formatExposure(exposureValue) // Model - model === 'FC7203' ? 'DJI Mavic Mini' : model + const formattedModel = model === 'FC7203' ? 'DJI Mavic Mini' : model return { date: date as string, iso, - model, + model: formattedModel, fstop, shutterspeed, focalLength, diff --git a/src/lib/exif/index.ts b/src/lib/exif/index.ts index 1aa03bd8..d35711a1 100644 --- a/src/lib/exif/index.ts +++ b/src/lib/exif/index.ts @@ -1,35 +1,2 @@ -import fs from 'node:fs' -import path from 'node:path' -import { read } from 'fast-exif' -import iptc from 'node-iptc' -import type { Exif, ExifFormatted } from './types.ts' -import { formatExif } from './format.ts' - -export async function readOutExif(filePath: string): Promise { - if (!filePath) return - - const imageId = path.basename(filePath, path.extname(filePath)) - - try { - // exif - const exifData = await read(filePath, true) - if (!exifData) return - - // iptc - const file = fs.readFileSync(filePath) - const iptcData = iptc(file) - - // format before output - const exifDataFormatted = formatExif(exifData) - - const exif = { - image: imageId, - exif: { ...exifDataFormatted } as ExifFormatted, - iptc: { ...iptcData } - } - - return exif - } catch (error: any) { - console.error(`${imageId}: ${error.message}`) - } -} +export * from './readOutExif' +export * from './types' diff --git a/src/lib/exif/readOutExif.ts b/src/lib/exif/readOutExif.ts new file mode 100644 index 00000000..1aa03bd8 --- /dev/null +++ b/src/lib/exif/readOutExif.ts @@ -0,0 +1,35 @@ +import fs from 'node:fs' +import path from 'node:path' +import { read } from 'fast-exif' +import iptc from 'node-iptc' +import type { Exif, ExifFormatted } from './types.ts' +import { formatExif } from './format.ts' + +export async function readOutExif(filePath: string): Promise { + if (!filePath) return + + const imageId = path.basename(filePath, path.extname(filePath)) + + try { + // exif + const exifData = await read(filePath, true) + if (!exifData) return + + // iptc + const file = fs.readFileSync(filePath) + const iptcData = iptc(file) + + // format before output + const exifDataFormatted = formatExif(exifData) + + const exif = { + image: imageId, + exif: { ...exifDataFormatted } as ExifFormatted, + iptc: { ...iptcData } + } + + return exif + } catch (error: any) { + console.error(`${imageId}: ${error.message}`) + } +} diff --git a/src/lib/exif/types.d.ts b/src/lib/exif/types.ts similarity index 100% rename from src/lib/exif/types.d.ts rename to src/lib/exif/types.ts diff --git a/src/lib/feed.test.ts b/src/lib/feed/feed.test.ts similarity index 96% rename from src/lib/feed.test.ts rename to src/lib/feed/feed.test.ts index 5f33f337..8b37cc0b 100644 --- a/src/lib/feed.test.ts +++ b/src/lib/feed/feed.test.ts @@ -1,5 +1,5 @@ import { it, describe, expect } from 'vitest' -import { getFeedContent } from './feed' +import { getFeedContent } from '.' describe('getFeedContent', () => { it('should generate post feed content with an image', async () => { diff --git a/src/lib/feed.ts b/src/lib/feed/feed.ts similarity index 91% rename from src/lib/feed.ts rename to src/lib/feed/feed.ts index 86e9fa3a..936d6955 100644 --- a/src/lib/feed.ts +++ b/src/lib/feed/feed.ts @@ -1,5 +1,5 @@ import type { CollectionEntry } from 'astro:content' -import { markdownToHtml } from './markdown' +import { markdownToHtml } from '../markdown' export async function getFeedContent( post: CollectionEntry<'articles' | 'photos' | 'links'> diff --git a/src/lib/feed/index.ts b/src/lib/feed/index.ts new file mode 100644 index 00000000..9dfd006f --- /dev/null +++ b/src/lib/feed/index.ts @@ -0,0 +1 @@ +export * from './feed' diff --git a/src/lib/github.test.ts b/src/lib/github/github.test.ts similarity index 97% rename from src/lib/github.test.ts rename to src/lib/github/github.test.ts index 7c519714..732712e4 100644 --- a/src/lib/github.test.ts +++ b/src/lib/github/github.test.ts @@ -1,5 +1,5 @@ import { it, describe, expect, vi } from 'vitest' -import { getRepo } from './github' +import { getRepo } from '.' describe('getRepo Function', () => { const mockResponseData = { diff --git a/src/lib/github.ts b/src/lib/github/github.ts similarity index 100% rename from src/lib/github.ts rename to src/lib/github/github.ts diff --git a/src/lib/github/index.ts b/src/lib/github/index.ts new file mode 100644 index 00000000..7680ea27 --- /dev/null +++ b/src/lib/github/index.ts @@ -0,0 +1 @@ +export * from './github' diff --git a/src/lib/remark-lead-paragraph/index.ts b/src/lib/remark-lead-paragraph/index.ts new file mode 100644 index 00000000..716a5abb --- /dev/null +++ b/src/lib/remark-lead-paragraph/index.ts @@ -0,0 +1 @@ +export * from './remark-lead-paragraph' diff --git a/src/lib/remark-lead-paragraph.test.ts b/src/lib/remark-lead-paragraph/remark-lead-paragraph.test.ts similarity index 95% rename from src/lib/remark-lead-paragraph.test.ts rename to src/lib/remark-lead-paragraph/remark-lead-paragraph.test.ts index 6c15a1fc..e07fbff0 100644 --- a/src/lib/remark-lead-paragraph.test.ts +++ b/src/lib/remark-lead-paragraph/remark-lead-paragraph.test.ts @@ -4,7 +4,7 @@ import remarkRehype from 'remark-rehype' import rehypeStringify from 'rehype-stringify' import { VFile } from 'vfile' import { test, expect, beforeAll } from 'vitest' -import remarkLeadParagraph, { type MyFile } from './remark-lead-paragraph' +import { remarkLeadParagraph, type MyFile } from '.' let processor: ReturnType diff --git a/src/lib/remark-lead-paragraph.ts b/src/lib/remark-lead-paragraph/remark-lead-paragraph.ts similarity index 95% rename from src/lib/remark-lead-paragraph.ts rename to src/lib/remark-lead-paragraph/remark-lead-paragraph.ts index 3692911d..67489cac 100644 --- a/src/lib/remark-lead-paragraph.ts +++ b/src/lib/remark-lead-paragraph/remark-lead-paragraph.ts @@ -17,7 +17,7 @@ export interface MyFile extends VFile { } } -export default function remarkLeadParagraph(): Transformer { +export function remarkLeadParagraph(): Transformer { return (tree, file) => { // Check if the file is the type we want to process if (!file.history[0]?.includes('articles')) return diff --git a/src/lib/remark-toc/index.ts b/src/lib/remark-toc/index.ts new file mode 100644 index 00000000..ac30e68a --- /dev/null +++ b/src/lib/remark-toc/index.ts @@ -0,0 +1 @@ +export * from './remark-toc' diff --git a/src/lib/remark-toc.test.ts b/src/lib/remark-toc/remark-toc.test.ts similarity index 95% rename from src/lib/remark-toc.test.ts rename to src/lib/remark-toc/remark-toc.test.ts index 7769464b..ba6af269 100644 --- a/src/lib/remark-toc.test.ts +++ b/src/lib/remark-toc/remark-toc.test.ts @@ -4,7 +4,7 @@ import remarkRehype from 'remark-rehype' import rehypeStringify from 'rehype-stringify' import { VFile } from 'vfile' import { test, expect } from 'vitest' -import remarkToc, { type MyFile } from './remark-toc' // Replace with the actual path +import { remarkToc, type MyFile } from '.' const expectedToc: string = `
  • diff --git a/src/lib/remark-toc.ts b/src/lib/remark-toc/remark-toc.ts similarity index 95% rename from src/lib/remark-toc.ts rename to src/lib/remark-toc/remark-toc.ts index 3fcaf650..2e97539d 100644 --- a/src/lib/remark-toc.ts +++ b/src/lib/remark-toc/remark-toc.ts @@ -19,7 +19,7 @@ export interface MyFile extends VFile { } } -export default function remarkToc(): Transformer { +export function remarkToc(): Transformer { return (tree, file) => { // Check if the file is the type we want to process if (!file.history[0]?.includes('articles')) return diff --git a/src/lib/slugify/index.ts b/src/lib/slugify/index.ts new file mode 100644 index 00000000..452800e4 --- /dev/null +++ b/src/lib/slugify/index.ts @@ -0,0 +1 @@ +export * from './slugify' diff --git a/src/lib/slugify.test.ts b/src/lib/slugify/slugify.test.ts similarity index 93% rename from src/lib/slugify.test.ts rename to src/lib/slugify/slugify.test.ts index a9a7cace..1c84d143 100644 --- a/src/lib/slugify.test.ts +++ b/src/lib/slugify/slugify.test.ts @@ -1,5 +1,5 @@ import { test, expect } from 'vitest' -import slugify, { slugifyAll } from './slugify' +import { slugify, slugifyAll } from '.' test('slugify should convert text to slug', () => { const text = 'Hello World!' diff --git a/src/lib/slugify.ts b/src/lib/slugify/slugify.ts similarity index 74% rename from src/lib/slugify.ts rename to src/lib/slugify/slugify.ts index cb6c1bfd..b061b555 100644 --- a/src/lib/slugify.ts +++ b/src/lib/slugify/slugify.ts @@ -1,8 +1,6 @@ import slugifyLib from 'slugify' -const slugify = (text: string) => +export const slugify = (text: string) => slugifyLib(text, { lower: true, remove: /[*+~.()'"!:@]/g }) export const slugifyAll = (arr: string[]) => arr.map((str) => slugify(str)) - -export default slugify diff --git a/src/lib/umami/index.ts b/src/lib/umami/index.ts new file mode 100644 index 00000000..e52f8b5e --- /dev/null +++ b/src/lib/umami/index.ts @@ -0,0 +1 @@ +export * from './umami' diff --git a/src/lib/umami.test.ts b/src/lib/umami/umami.test.ts similarity index 96% rename from src/lib/umami.test.ts rename to src/lib/umami/umami.test.ts index 374e04a7..b843f2cc 100644 --- a/src/lib/umami.test.ts +++ b/src/lib/umami/umami.test.ts @@ -1,5 +1,5 @@ import { test, expect } from 'vitest' -import { getUmamiConfig } from './umami' +import { getUmamiConfig } from '.' test('should throw an error if Umami environment variables are missing in production', () => { const mockEnv = { diff --git a/src/lib/umami.ts b/src/lib/umami/umami.ts similarity index 100% rename from src/lib/umami.ts rename to src/lib/umami/umami.ts