Skip to content

Commit f1d1e1f

Browse files
committed
docs: Improved example app: the photos are now shown with EXIF data thanks to SagaImageReader 1.2.0
1 parent 9c1a48b commit f1d1e1f

File tree

11 files changed

+93
-13
lines changed

11 files changed

+93
-13
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,3 @@
66
Package.resolved
77
.claude
88
docs/
9-
plan.md

Example/Package.resolved

Lines changed: 11 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Example/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ let package = Package(
1111
.package(path: "../"),
1212
.package(url: "https://github.com/loopwerk/SagaParsleyMarkdownReader", from: "1.0.0"),
1313
.package(url: "https://github.com/loopwerk/SagaSwimRenderer", from: "1.0.0"),
14-
.package(url: "https://github.com/loopwerk/SagaImageReader", from: "1.0.0"),
14+
.package(url: "https://github.com/loopwerk/SagaImageReader", from: "1.2.0"),
1515
.package(url: "https://github.com/loopwerk/Moon", from: "1.0.0"),
1616
],
1717
targets: [

Example/Sources/Example/main.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ struct MusicVideoMetadata: Metadata {
3030
}
3131

3232
struct AlbumMetadata: Metadata {}
33-
struct PhotoMetadata: Metadata {}
3433

3534
struct ArtistMetadata: Metadata {
3635
let genre: String
@@ -126,7 +125,7 @@ try await Saga(input: "content", output: "deploy")
126125
],
127126
nested: { nested in
128127
nested.register(
129-
metadata: PhotoMetadata.self,
128+
metadata: ImageMetadata.self,
130129
readers: [.imageReader],
131130
writers: [
132131
.itemWriter(swim(renderPhoto)),

Example/Sources/Example/templates.swift

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Moon
44
import Saga
55
import SagaPathKit
66
import SagaSwimRenderer
7+
import SagaImageReader
78

89
// MARK: - Helpers
910

@@ -173,7 +174,7 @@ func renderAlbums(context: ItemsRenderingContext<AlbumMetadata>) -> Node {
173174

174175
div(class: "collections-grid") {
175176
context.items.map { album in
176-
let photos = album.children(as: PhotoMetadata.self)
177+
let photos = album.children(as: ImageMetadata.self)
177178
let previewPhotos = Array(photos.prefix(4))
178179
let folder = album.relativeSource.parent()
179180

@@ -185,7 +186,10 @@ func renderAlbums(context: ItemsRenderingContext<AlbumMetadata>) -> Node {
185186
}
186187
div(class: "card-info") {
187188
h2 { album.title }
188-
p { "\(photos.count) photos" }
189+
p {
190+
Node.raw(album.body.withoutHtmlTags)
191+
"\(photos.count) photos."
192+
}
189193
}
190194
}
191195
}
@@ -195,7 +199,7 @@ func renderAlbums(context: ItemsRenderingContext<AlbumMetadata>) -> Node {
195199
}
196200

197201
func renderAlbum(context: ItemRenderingContext<AlbumMetadata>) -> Node {
198-
let photos = context.item.children(as: PhotoMetadata.self)
202+
let photos = context.item.children(as: ImageMetadata.self)
199203

200204
return baseHtml(title: context.item.title) {
201205
div(class: "album") {
@@ -222,7 +226,7 @@ func renderAlbum(context: ItemRenderingContext<AlbumMetadata>) -> Node {
222226
}
223227
}
224228

225-
func renderPhoto(context: ItemRenderingContext<PhotoMetadata>) -> Node {
229+
func renderPhoto(context: ItemRenderingContext<ImageMetadata>) -> Node {
226230
let album = context.item.parent(as: AlbumMetadata.self)
227231

228232
let imageSrc = "../\(context.item.relativeSource.lastComponent)"
@@ -244,6 +248,53 @@ func renderPhoto(context: ItemRenderingContext<PhotoMetadata>) -> Node {
244248
div(class: "photo-full") {
245249
img(alt: context.item.title, src: imageSrc)
246250
}
251+
252+
renderExifInfo(context.item.metadata)
253+
}
254+
}
255+
}
256+
257+
@NodeBuilder
258+
func renderExifInfo(_ m: ImageMetadata) -> Node {
259+
let rows: [(String, String?)] = [
260+
("Camera", [m.make, m.model].compactMap { $0 }.joined(separator: " ")),
261+
("Lens", m.lensModel),
262+
("Focal Length", m.focalLength.map { "\($0)mm" }),
263+
("Focal Length (35mm)", m.focalLenIn35mmFilm.map { "\($0)mm" }),
264+
("Aperture", m.fNumber.map { "f/\($0)" }),
265+
("Exposure", m.exposureTime.map { "\($0)s" }),
266+
("ISO", m.iso.map { "\($0)" }),
267+
("Flash", m.flash.map { $0 == 0 ? "No" : "Yes" }),
268+
("Dimensions", {
269+
if let w = m.pixelXDimension, let h = m.pixelYDimension { return "\(w) x \(h)" }
270+
return nil
271+
}()),
272+
("Software", m.software),
273+
("Date", m.dateTimeOriginal),
274+
("Altitude", m.gpsAltitude.map { "\($0)m" }),
275+
]
276+
277+
let available = rows.compactMap { label, value in
278+
value.flatMap { $0.isEmpty ? nil : (label, $0) }
279+
}
280+
281+
let hasGPS = m.gpsLatitude != nil && m.gpsLongitude != nil
282+
283+
if !available.isEmpty || hasGPS {
284+
dl(class: "exif-info") {
285+
available.map { (label, value) in
286+
[dt { label }, dd { value }]
287+
}
288+
289+
if let lat = m.gpsLatitude, let latRef = m.gpsLatitudeRef,
290+
let lon = m.gpsLongitude, let lonRef = m.gpsLongitudeRef {
291+
let signedLat = latRef == "S" ? "-\(lat)" : lat
292+
let signedLon = lonRef == "W" ? "-\(lon)" : lon
293+
let mapsURL = "https://maps.apple.com/?ll=\(signedLat),\(signedLon)&q=\(signedLat),\(signedLon)"
294+
295+
dt { "GPS" }
296+
dd { a(href: mapsURL, target: "_blank") { "\(lat)\(latRef), \(lon)\(lonRef)" } }
297+
}
247298
}
248299
}
249300
}
212 KB
Loading
181 KB
Loading
152 KB
Loading
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Towers
2+
These pics have EXIF data!

Example/content/static/style.css

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,29 @@ main h2 {
361361
border-radius: 4px;
362362
}
363363

364+
/* EXIF info */
365+
.exif-info {
366+
display: grid;
367+
grid-template-columns: auto 1fr;
368+
gap: 0.35rem 1.25rem;
369+
background: #252525;
370+
border-radius: 8px;
371+
padding: 1.25rem 1.5rem;
372+
margin-top: 1.5rem;
373+
width: 100%;
374+
max-width: 500px;
375+
font-size: 0.85rem;
376+
}
377+
378+
.exif-info dt {
379+
color: #888;
380+
white-space: nowrap;
381+
}
382+
383+
.exif-info dd {
384+
color: #e0e0e0;
385+
}
386+
364387
/* Videos */
365388
.video-grid {
366389
display: grid;

0 commit comments

Comments
 (0)