Merge photo highlights by name and capture year
This commit is contained in:
+3
-1
@@ -3,7 +3,9 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017"
|
||||||
date: "2026-01-16T20:02:00.721000+03:30"
|
date: "2026-01-16T20:02:00.721000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
anchor: "Iran"
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<div id="photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017"></div>
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/00.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/00.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-01"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-01"
|
||||||
date: "2026-01-19T14:54:34.806000+03:30"
|
date: "2026-01-19T14:54:34.806000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/01.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/01.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-02"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-02"
|
||||||
date: "2026-01-21T16:33:29.339000+03:30"
|
date: "2026-01-21T16:33:29.339000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/02.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/02.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-03"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-03"
|
||||||
date: "2026-01-24T14:04:39.306000+03:30"
|
date: "2026-01-24T14:04:39.306000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/03.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/03.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-04"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-04"
|
||||||
date: "2026-01-24T15:18:34.557000+03:30"
|
date: "2026-01-24T15:18:34.557000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/04.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/04.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-05"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-05"
|
||||||
date: "2026-01-28T17:07:06.982000+03:30"
|
date: "2026-01-28T17:07:06.982000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/05.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/05.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-06"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-06"
|
||||||
date: "2026-02-02T08:03:58.683000+03:30"
|
date: "2026-02-02T08:03:58.683000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/06.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/06.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-07"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-07"
|
||||||
date: "2026-02-06T15:56:02.032000+03:30"
|
date: "2026-02-06T15:56:02.032000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/07.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/07.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-08"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-08"
|
||||||
date: "2026-02-06T19:01:35.759000+03:30"
|
date: "2026-02-06T19:01:35.759000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/08.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/08.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-09"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-09"
|
||||||
date: "2026-02-06T19:04:14.947000+03:30"
|
date: "2026-02-06T19:04:14.947000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/09.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/09.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-10"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-10"
|
||||||
date: "2026-02-07T20:49:41.304000+03:30"
|
date: "2026-02-07T20:49:41.304000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/10.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/10.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-11"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-11"
|
||||||
date: "2026-02-14T15:15:35.920000+03:30"
|
date: "2026-02-14T15:15:35.920000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/11.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/11.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-12"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-12"
|
||||||
date: "2026-02-20T14:58:05.265000+03:30"
|
date: "2026-02-20T14:58:05.265000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/12.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/12.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-13"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-13"
|
||||||
date: "2026-02-26T11:56:39.486000+03:30"
|
date: "2026-02-26T11:56:39.486000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/13.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/13.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-01"
|
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-01"
|
||||||
date: "2026-03-06T13:31:34.372000+03:30"
|
date: "2026-03-06T13:31:34.372000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/01.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/01.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-02"
|
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-02"
|
||||||
date: "2026-03-06T14:48:51.818000+03:30"
|
date: "2026-03-06T14:48:51.818000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/02.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/02.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-14"
|
title: "photo-a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017-14"
|
||||||
date: "2026-03-06T15:11:26.932000+03:30"
|
date: "2026-03-06T15:11:26.932000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/14.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017/14.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+3
-1
@@ -3,7 +3,9 @@ layout: post
|
|||||||
title: "photo-bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace"
|
title: "photo-bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace"
|
||||||
date: "2026-03-07T11:58:57.224000+04:00"
|
date: "2026-03-07T11:58:57.224000+04:00"
|
||||||
categories: art
|
categories: art
|
||||||
anchor: "Armenia"
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<div id="photo-bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace"></div>
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace/00.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace/00.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace-01"
|
title: "photo-bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace-01"
|
||||||
date: "2026-03-07T12:34:32.793000+04:00"
|
date: "2026-03-07T12:34:32.793000+04:00"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace/01.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace/01.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace-02"
|
title: "photo-bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace-02"
|
||||||
date: "2026-03-07T15:33:07.690000+04:00"
|
date: "2026-03-07T15:33:07.690000+04:00"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace/02.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace/02.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+3
-1
@@ -3,7 +3,9 @@ layout: post
|
|||||||
title: "photo-3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278"
|
title: "photo-3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278"
|
||||||
date: "2026-06-26T16:53:49.633000+04:00"
|
date: "2026-06-26T16:53:49.633000+04:00"
|
||||||
categories: art
|
categories: art
|
||||||
anchor: "Armenia"
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<div id="photo-3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278"></div>
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278/00.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278/00.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278-01"
|
title: "photo-3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278-01"
|
||||||
date: "2026-06-26T17:15:56.830000+04:00"
|
date: "2026-06-26T17:15:56.830000+04:00"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278/01.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278/01.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278-02"
|
title: "photo-3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278-02"
|
||||||
date: "2026-06-26T17:17:37.263000+04:00"
|
date: "2026-06-26T17:17:37.263000+04:00"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278/02.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278/02.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-03"
|
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-03"
|
||||||
date: "2026-08-25T11:29:18.840000+03:30"
|
date: "2026-08-25T11:29:18.840000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/03.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/03.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-04"
|
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-04"
|
||||||
date: "2026-08-28T18:42:14.080000+03:30"
|
date: "2026-08-28T18:42:14.080000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/04.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/04.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-05"
|
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-05"
|
||||||
date: "2026-08-28T21:03:02.299000+03:30"
|
date: "2026-08-28T21:03:02.299000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/05.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/05.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-06"
|
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-06"
|
||||||
date: "2026-08-28T21:35:02.917000+03:30"
|
date: "2026-08-28T21:35:02.917000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/06.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/06.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-07"
|
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-07"
|
||||||
date: "2026-08-30T18:27:21.073000+03:30"
|
date: "2026-08-30T18:27:21.073000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/07.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/07.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-08"
|
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-08"
|
||||||
date: "2026-08-30T18:30:02.249000+03:30"
|
date: "2026-08-30T18:30:02.249000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/08.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/08.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-09"
|
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-09"
|
||||||
date: "2026-09-01T14:21:37.968000+03:30"
|
date: "2026-09-01T14:21:37.968000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/09.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/09.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+2
@@ -3,6 +3,8 @@ layout: post
|
|||||||
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-10"
|
title: "photo-0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172-10"
|
||||||
date: "2026-09-19T20:21:02.987000+03:30"
|
date: "2026-09-19T20:21:02.987000+03:30"
|
||||||
categories: art
|
categories: art
|
||||||
|
anchor: "Iran"
|
||||||
|
highlight_name: "Iran"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/10.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172/10.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-474ab3283ce8801ac6e59b67b65b4169167053873a5a8db4a15b840a3448266c"
|
title: "photo-474ab3283ce8801ac6e59b67b65b4169167053873a5a8db4a15b840a3448266c"
|
||||||
date: "2026-09-19T12:40:18+00:00"
|
date: "2026-09-19T12:40:18+00:00"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
<div id="photo-474ab3283ce8801ac6e59b67b65b4169167053873a5a8db4a15b840a3448266c"></div>
|
<div id="photo-474ab3283ce8801ac6e59b67b65b4169167053873a5a8db4a15b840a3448266c"></div>
|
||||||
|
|||||||
+2
-1
@@ -3,7 +3,8 @@ layout: post
|
|||||||
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d"
|
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d"
|
||||||
date: "2026-09-19T12:40:33+00:00"
|
date: "2026-09-19T12:40:33+00:00"
|
||||||
categories: art
|
categories: art
|
||||||
anchor: "Romania"
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<div id="photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d"></div>
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/00.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/00.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-04"
|
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-04"
|
||||||
date: "2026-09-19T12:40:19+00:00"
|
date: "2026-09-19T12:40:19+00:00"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/04.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/04.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-05"
|
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-05"
|
||||||
date: "2026-09-19T12:40:20+00:00"
|
date: "2026-09-19T12:40:20+00:00"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/05.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/05.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-06"
|
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-06"
|
||||||
date: "2026-09-19T12:40:21+00:00"
|
date: "2026-09-19T12:40:21+00:00"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/06.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/06.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-07"
|
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-07"
|
||||||
date: "2026-09-19T12:40:22+00:00"
|
date: "2026-09-19T12:40:22+00:00"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/07.jpg" alt="Transmission of Flesh by Erfan Ashourioun" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/07.jpg" alt="Transmission of Flesh by Erfan Ashourioun" loading="lazy"></p>
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ layout: post
|
|||||||
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-08"
|
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-08"
|
||||||
date: "2026-09-19T12:40:23+00:00"
|
date: "2026-09-19T12:40:23+00:00"
|
||||||
categories: art
|
categories: art
|
||||||
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/08.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/08.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+3
-1
@@ -3,7 +3,9 @@ layout: post
|
|||||||
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-09"
|
title: "photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-09"
|
||||||
date: "2026-09-19T12:40:24+00:00"
|
date: "2026-09-19T12:40:24+00:00"
|
||||||
categories: art
|
categories: art
|
||||||
anchor: "Armenia"
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<div id="photo-7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d-09"></div>
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/09.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/09.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
+2
@@ -3,6 +3,8 @@ layout: post
|
|||||||
title: "photo-3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278-03"
|
title: "photo-3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278-03"
|
||||||
date: "2026-09-26T18:27:11.763827+00:00"
|
date: "2026-09-26T18:27:11.763827+00:00"
|
||||||
categories: art
|
categories: art
|
||||||
|
anchor: "Armenia"
|
||||||
|
highlight_name: "Armenia"
|
||||||
---
|
---
|
||||||
|
|
||||||
<p><img src="/img/arts/uploads/3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278/03.jpg" alt="" loading="lazy"></p>
|
<p><img src="/img/arts/uploads/3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278/03.jpg" alt="" loading="lazy"></p>
|
||||||
|
|||||||
@@ -179,8 +179,11 @@ photos. When none of these date sources is available, the service uses the uploa
|
|||||||
date. Re-sharing the same images, caption, and
|
date. Re-sharing the same images, caption, and
|
||||||
highlight with dates replaces the earlier undated upload. Captions are plain
|
highlight with dates replaces the earlier undated upload. Captions are plain
|
||||||
text and optional.
|
text and optional.
|
||||||
An optional highlight name (up to 200 characters) adds one link to **Highlights**,
|
An optional highlight name (up to 200 characters) adds a link to **Highlights**.
|
||||||
pointing to the first photo in the batch. Leave it blank for an ordinary upload.
|
If that name already exists in the same capture year, publishing merges the new
|
||||||
|
photos into that highlight and keeps one link at its newest photo. A batch spanning
|
||||||
|
years gets one link per year. Photo dates and gallery order stay unchanged. Leave
|
||||||
|
the name blank for an ordinary upload.
|
||||||
|
|
||||||
Gallery images are progressive JPEGs with a maximum edge of 1600 pixels and a
|
Gallery images are progressive JPEGs with a maximum edge of 1600 pixels and a
|
||||||
300 KiB size limit. The uploader tries moderate JPEG quality levels, then reduces
|
300 KiB size limit. The uploader tries moderate JPEG quality levels, then reduces
|
||||||
|
|||||||
@@ -177,6 +177,8 @@ def photo_entry(job, date, index, caption, highlight):
|
|||||||
f'date: "{item_date.isoformat()}"', "categories: art"]
|
f'date: "{item_date.isoformat()}"', "categories: art"]
|
||||||
if index == 0 and highlight:
|
if index == 0 and highlight:
|
||||||
content.append(f"anchor: {json.dumps(highlight)}")
|
content.append(f"anchor: {json.dumps(highlight)}")
|
||||||
|
if highlight:
|
||||||
|
content.append(f"highlight_name: {json.dumps(highlight)}")
|
||||||
content.extend(["---", ""])
|
content.extend(["---", ""])
|
||||||
if index == 0 and not highlight:
|
if index == 0 and not highlight:
|
||||||
content.extend([f'<div id="photo-{job}"></div>', ""])
|
content.extend([f'<div id="photo-{job}"></div>', ""])
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
"""Keep one gallery highlight link per name and capture year."""
|
||||||
|
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
def field(content, name):
|
||||||
|
match = re.search(rf"^{re.escape(name)}: (.+)$", content.split("---", 2)[1], re.MULTILINE)
|
||||||
|
if not match:
|
||||||
|
return None
|
||||||
|
value = match.group(1).strip()
|
||||||
|
return json.loads(value) if value.startswith('"') else value
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_highlights(art):
|
||||||
|
"""Place each link on the newest photo in its named, dated group."""
|
||||||
|
groups = {}
|
||||||
|
for path in Path(art).glob("*.md"):
|
||||||
|
content = path.read_text()
|
||||||
|
name = field(content, "highlight_name") or field(content, "anchor")
|
||||||
|
date = field(content, "date")
|
||||||
|
if not name or not date:
|
||||||
|
continue
|
||||||
|
taken = datetime.fromisoformat(str(date))
|
||||||
|
if taken.tzinfo is None:
|
||||||
|
taken = taken.replace(tzinfo=timezone.utc)
|
||||||
|
groups.setdefault((name, taken.year), []).append((taken, path, content))
|
||||||
|
|
||||||
|
changed = []
|
||||||
|
for (name, _), entries in groups.items():
|
||||||
|
# An old single anchor is already the only link; a newer named photo
|
||||||
|
# moves the link without changing any photo's capture date or position.
|
||||||
|
newest = max(entries, key=lambda entry: (entry[0], entry[1].name))[1]
|
||||||
|
if len(entries) == 1 and field(entries[0][2], "anchor") == name:
|
||||||
|
continue
|
||||||
|
for _, path, content in entries:
|
||||||
|
old = content
|
||||||
|
had_anchor = field(content, "anchor") is not None
|
||||||
|
if (path == newest and had_anchor and
|
||||||
|
all(field(other[2], "anchor") is None for other in entries if other[1] != path)):
|
||||||
|
continue
|
||||||
|
if had_anchor:
|
||||||
|
content = re.sub(r"^anchor: .+\n", "", content, count=1, flags=re.MULTILINE)
|
||||||
|
if path == newest:
|
||||||
|
content = content.replace("categories: art\n", "categories: art\n" +
|
||||||
|
f"anchor: {json.dumps(name, ensure_ascii=False)}\n", 1)
|
||||||
|
elif had_anchor:
|
||||||
|
title = field(content, "title")
|
||||||
|
if title and title.startswith("photo-") and f'id="{title}"' not in content:
|
||||||
|
content = content.replace("---\n\n", f'---\n\n<div id="{title}"></div>\n\n', 1)
|
||||||
|
if content != old:
|
||||||
|
path.write_text(content)
|
||||||
|
changed.append(path)
|
||||||
|
return changed
|
||||||
@@ -11,6 +11,7 @@ import sys
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from app import atomic_json
|
from app import atomic_json
|
||||||
|
from highlights import normalize_highlights
|
||||||
from posts import publish_post
|
from posts import publish_post
|
||||||
|
|
||||||
log = logging.getLogger("publisher")
|
log = logging.getLogger("publisher")
|
||||||
@@ -117,6 +118,8 @@ class Publisher:
|
|||||||
self.git("add", "--", str(entry))
|
self.git("add", "--", str(entry))
|
||||||
shutil.copytree(submission / "images", self.repo / images, dirs_exist_ok=True)
|
shutil.copytree(submission / "images", self.repo / images, dirs_exist_ok=True)
|
||||||
self.git("add", "--", str(images))
|
self.git("add", "--", str(images))
|
||||||
|
for path in normalize_highlights(self.repo / "_art"):
|
||||||
|
self.git("add", "--", str(path.relative_to(self.repo)))
|
||||||
if self.git("diff", "--cached", "--name-only"):
|
if self.git("diff", "--cached", "--name-only"):
|
||||||
self.git("commit", "-m", f"Publish {len(jobs)} submission(s)")
|
self.git("commit", "-m", f"Publish {len(jobs)} submission(s)")
|
||||||
self.git("push", "origin", f"HEAD:refs/heads/{self.branch}")
|
self.git("push", "origin", f"HEAD:refs/heads/{self.branch}")
|
||||||
|
|||||||
@@ -379,6 +379,56 @@ def test_publisher_names_photo_entry_from_capture_date(publisher, service):
|
|||||||
assert f'_art/2025-04-18-photo-{response.json["id"]}-00.md' in paths
|
assert f'_art/2025-04-18-photo-{response.json["id"]}-00.md' in paths
|
||||||
|
|
||||||
|
|
||||||
|
def test_publisher_merges_highlights_by_name_and_capture_year(publisher):
|
||||||
|
run, remote, client = publisher
|
||||||
|
first = client.post("/api/photos", headers=AUTH, data={
|
||||||
|
"photos": [(io.BytesIO(photo("red")), "first.jpg")],
|
||||||
|
"highlight": "Trip", "photo_dates": "2026-03-01T12:00:00+00:00",
|
||||||
|
}).json["id"]
|
||||||
|
assert run().returncode == 0
|
||||||
|
second = client.post("/api/photos", headers=AUTH, data={
|
||||||
|
"photos": [(io.BytesIO(photo("blue")), "second.jpg")],
|
||||||
|
"highlight": "Trip", "photo_dates": "2026-06-01T12:00:00+00:00",
|
||||||
|
}).json["id"]
|
||||||
|
assert run().returncode == 0
|
||||||
|
files = git(remote, "ls-tree", "-r", "--name-only", "master").splitlines()
|
||||||
|
entries = [git(remote, "show", f"master:{path}") for path in files if path.startswith("_art/")]
|
||||||
|
assert sum('anchor: "Trip"' in entry for entry in entries) == 1
|
||||||
|
assert f'anchor: "Trip"' in next(entry for entry in entries if f"photo-{second}" in entry)
|
||||||
|
assert f'<div id="photo-{first}"></div>' in next(
|
||||||
|
entry for entry in entries if f'title: "photo-{first}"' in entry)
|
||||||
|
old_year = client.post("/api/photos", headers=AUTH, data={
|
||||||
|
"photos": [(io.BytesIO(photo("green")), "old-year.jpg")],
|
||||||
|
"highlight": "Trip", "photo_dates": "2025-12-31T12:00:00+00:00",
|
||||||
|
}).json["id"]
|
||||||
|
assert run().returncode == 0
|
||||||
|
files = git(remote, "ls-tree", "-r", "--name-only", "master").splitlines()
|
||||||
|
entries = [git(remote, "show", f"master:{path}") for path in files if path.startswith("_art/")]
|
||||||
|
assert sum('anchor: "Trip"' in entry for entry in entries) == 2
|
||||||
|
assert 'anchor: "Trip"' in next(entry for entry in entries if f"photo-{old_year}" in entry)
|
||||||
|
commit = git(remote, "rev-parse", "master")
|
||||||
|
assert run().returncode == 0
|
||||||
|
assert git(remote, "rev-parse", "master") == commit
|
||||||
|
|
||||||
|
|
||||||
|
def test_publisher_splits_a_highlight_across_capture_years(publisher):
|
||||||
|
run, remote, client = publisher
|
||||||
|
response = client.post("/api/photos", headers=AUTH, data={
|
||||||
|
"photos": [(io.BytesIO(photo("red")), "old.jpg"),
|
||||||
|
(io.BytesIO(photo("blue")), "new.jpg")],
|
||||||
|
"highlight": "Trip",
|
||||||
|
"photo_dates": "2025-12-31T12:00:00+00:00\n2026-01-01T12:00:00+00:00",
|
||||||
|
})
|
||||||
|
assert response.status_code == 202
|
||||||
|
result = run()
|
||||||
|
assert result.returncode == 0, result.stderr
|
||||||
|
job = response.json["id"]
|
||||||
|
files = git(remote, "ls-tree", "-r", "--name-only", "master").splitlines()
|
||||||
|
entries = [git(remote, "show", f"master:{path}") for path in files if f"photo-{job}" in path]
|
||||||
|
assert len(entries) == 2
|
||||||
|
assert all('anchor: "Trip"' in entry for entry in entries)
|
||||||
|
|
||||||
|
|
||||||
def test_publisher_replaces_an_undated_version_of_the_same_photos(publisher, service):
|
def test_publisher_replaces_an_undated_version_of_the_same_photos(publisher, service):
|
||||||
run, remote, client = publisher
|
run, remote, client = publisher
|
||||||
raw = photo()
|
raw = photo()
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
"""One-time migration of existing Iran and Armenia photo groups."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
sys.path.insert(0, str(ROOT / "photo-upload"))
|
||||||
|
from highlights import normalize_highlights
|
||||||
|
|
||||||
|
ART = ROOT / "_art"
|
||||||
|
IRAN = (
|
||||||
|
"0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172",
|
||||||
|
"a85137ab7990cb095c8043cf21c034663795194e5510f26a7175edf5a5489017",
|
||||||
|
)
|
||||||
|
ARMENIA = (
|
||||||
|
"bcf8d1409da4d748b2ba060fc090bbe5a518f033f3e971e95f89a8add5c74ace",
|
||||||
|
"3c708b27ab8e8af18bd3ad8ce25876be653b366551f065f31800d8c640b56278",
|
||||||
|
"474ab3283ce8801ac6e59b67b65b4169167053873a5a8db4a15b840a3448266c",
|
||||||
|
)
|
||||||
|
|
||||||
|
for path in ART.glob("*photo-*.md"):
|
||||||
|
if not path.name.startswith("2026-"):
|
||||||
|
continue
|
||||||
|
job = path.name.split("-photo-", 1)[1][:64]
|
||||||
|
name = "Iran" if job in IRAN else "Armenia" if job in ARMENIA else None
|
||||||
|
if job == "7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d":
|
||||||
|
index = int(path.stem[-2:])
|
||||||
|
name = "Armenia" if index >= 4 else None
|
||||||
|
if not name:
|
||||||
|
continue
|
||||||
|
content = path.read_text()
|
||||||
|
if "highlight_name:" not in content:
|
||||||
|
content = content.replace("categories: art\n", "categories: art\n" +
|
||||||
|
f"highlight_name: {json.dumps(name)}\n", 1)
|
||||||
|
path.write_text(content)
|
||||||
|
|
||||||
|
normalize_highlights(ART)
|
||||||
@@ -83,10 +83,24 @@ class PhotoHighlightTests(unittest.TestCase):
|
|||||||
records.sort(reverse=True)
|
records.sort(reverse=True)
|
||||||
grouped = [record for record in records if record[1] in ARMENIA + ROMANIA]
|
grouped = [record for record in records if record[1] in ARMENIA + ROMANIA]
|
||||||
self.assertEqual([record[1] for record in grouped], ROMANIA + ARMENIA)
|
self.assertEqual([record[1] for record in grouped], ROMANIA + ARMENIA)
|
||||||
self.assertEqual(grouped[0][2], "Romania")
|
# Newer uploads now own the one link for each name/year.
|
||||||
self.assertEqual(grouped[9][2], "Armenia")
|
self.assertIsNone(grouped[0][2])
|
||||||
|
self.assertIsNone(grouped[9][2])
|
||||||
self.assertIn("Transmission of Flesh by Erfan Ashourioun", grouped[11][3])
|
self.assertIn("Transmission of Flesh by Erfan Ashourioun", grouped[11][3])
|
||||||
|
|
||||||
|
def test_iran_and_armenia_have_one_link_each_in_2026(self):
|
||||||
|
for name in ("Iran", "Armenia"):
|
||||||
|
anchors = []
|
||||||
|
for path in ART.glob("2026-*.md"):
|
||||||
|
content = path.read_text()
|
||||||
|
if f'anchor: "{name}"' in content:
|
||||||
|
anchors.append(path)
|
||||||
|
self.assertEqual(len(anchors), 1, (name, anchors))
|
||||||
|
iran = next(path for path in ART.glob("2026-*.md")
|
||||||
|
if 'anchor: "Iran"' in path.read_text())
|
||||||
|
self.assertIn("0b1781e580e6d0852728b6aab4f45f0eded30394ea8ff74d9d7ce8ae326bd172",
|
||||||
|
iran.name)
|
||||||
|
|
||||||
def test_2026_highlights_follow_supplied_chronology(self):
|
def test_2026_highlights_follow_supplied_chronology(self):
|
||||||
anchors = {}
|
anchors = {}
|
||||||
for path in ART.glob("*photo-*.md"):
|
for path in ART.glob("*photo-*.md"):
|
||||||
|
|||||||
Reference in New Issue
Block a user