2
0
mirror of https://github.com/thumbsup/thumbsup synced 2024-11-07 15:20:26 +00:00

thumbsup v2: rewrite the website around 'albums'

This commit is contained in:
Romain Prieto 2016-10-10 22:49:08 +11:00
parent fa05959631
commit c2f290bbd6
46 changed files with 2392 additions and 816 deletions

View File

@ -14,11 +14,11 @@ var opts = yargs
description: 'Output path for the static website',
},
'index': {
description: 'Name of the First page in the flow. Defaults to index.html'
description: 'Name of the First page in the flow. Defaults to index.html'
},
'title': {
description: 'Website title',
default: 'My gallery'
default: 'Photo album'
},
'thumb-size': {
description: 'Thumbnail size in pixels (square)',

146
docs/index-captions.html Normal file
View File

@ -0,0 +1,146 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>Photo album - captions</title>
<link rel="stylesheet" href="public/reset.css" />
<link rel="stylesheet" href="public/light-gallery/css/lightgallery.css" />
<link rel="stylesheet" href="public/video-js.css" />
<link rel="stylesheet" href="public/theme.css" />
</head>
<body>
<header>
<h1>Photo album</h1>
<h2></h2>
</header>
<section id="sidebar">
<nav>
<!-- This album -->
<a href="index.html">
Home<span class="count">24</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-photos.html">
-
photos<span class="count">3</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-videos.html">
-
videos<span class="count">2</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-captions.html">
-
captions<span class="count">3</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-rotations.html">
-
rotations<span class="count">16</span>
</a>
<!-- And nested album -->
</nav>
</section>
<section id="content">
<nav class="breadcrumbs">
<a class="breadcrumb-item" href="index.html">Home </a><span class="breadcrumb-item active">captions</span>
</nav>
<ul id="albums">
</ul>
<ul id="gallery">
<li data-src="media/large/captions/sunset.jpg"
data-sub-html="Beach"
data-download-url="media/large/captions/sunset.jpg">
<a href="media/large/captions/sunset.jpg">
<img src="media/thumbs/captions/sunset.jpg"
width="120"
height="120"
alt="sunset.jpg" />
</a>
</li>
<li data-src="media/large/captions/tree.jpg"
data-sub-html="Autum"
data-download-url="media/large/captions/tree.jpg">
<a href="media/large/captions/tree.jpg">
<img src="media/thumbs/captions/tree.jpg"
width="120"
height="120"
alt="tree.jpg" />
</a>
</li>
<li data-src="media/large/captions/water.jpg"
data-sub-html="Sea"
data-download-url="media/large/captions/water.jpg">
<a href="media/large/captions/water.jpg">
<img src="media/thumbs/captions/water.jpg"
width="120"
height="120"
alt="water.jpg" />
</a>
</li>
</ul>
<div id="videos">
</div>
</section>
<!-- jQuery -->
<script src="public/jquery.min.js"></script>
<!-- VideoJS -->
<script src="public/video.js"></script>
<!-- LightGallery -->
<script src="public/light-gallery/js/lightgallery.js"></script>
<script src="public/light-gallery/js/lg-autoplay.js"></script>
<script src="public/light-gallery/js/lg-pager.js"></script>
<script src="public/light-gallery/js/lg-thumbnail.js"></script>
<script src="public/light-gallery/js/lg-video.js"></script>
<script>
$(document).ready(function() {
$("#gallery").lightGallery({
thumbWidth: 80,
controls: true,
loop : false,
download: true,
counter: true,
videojs: true
});
});
</script>
</body>
</html>

View File

@ -13,30 +13,13 @@
<body>
<header>
<a href="index.html">
<h1>Photo</h1>
<h2>gallery</h2>
</a>
</header>
<nav>
<ul>
<li >
<a href="photos.html">photos</a>
</li>
<li >
<a href="videos.html">videos</a>
</li>
<li class="active">
<a href="captions.html">captions</a>
</li>
<li >
<a href="rotations.html">rotations</a>
</li>
</ul>
Breadcrumbs
</nav>
<ul id="albums">
</ul>
<ul id="gallery">
<li data-src="media/large/captions/sunset.jpg"
data-sub-html="Beach"
@ -45,7 +28,7 @@
<img src="media/thumbs/captions/sunset.jpg"
width="120"
height="120"
alt="sunset.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/captions/tree.jpg"
@ -55,7 +38,7 @@
<img src="media/thumbs/captions/tree.jpg"
width="120"
height="120"
alt="tree.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/captions/water.jpg"
@ -65,7 +48,7 @@
<img src="media/thumbs/captions/water.jpg"
width="120"
height="120"
alt="water.jpg" />
alt="" />
</a>
</li>
</ul>

View File

@ -13,30 +13,13 @@
<body>
<header>
<a href="index.html">
<h1>Photo</h1>
<h2>gallery</h2>
</a>
</header>
<nav>
<ul>
<li class="active">
<a href="photos.html">photos</a>
</li>
<li >
<a href="videos.html">videos</a>
</li>
<li >
<a href="captions.html">captions</a>
</li>
<li >
<a href="rotations.html">rotations</a>
</li>
</ul>
Breadcrumbs
</nav>
<ul id="albums">
</ul>
<ul id="gallery">
<li data-src="media/large/photos/port-stephens.jpg"
data-sub-html=""
@ -45,7 +28,7 @@
<img src="media/thumbs/photos/port-stephens.jpg"
width="120"
height="120"
alt="port-stephens.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/photos/port-douglas1.jpg"
@ -55,7 +38,7 @@
<img src="media/thumbs/photos/port-douglas1.jpg"
width="120"
height="120"
alt="port-douglas1.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/photos/port-douglas2.jpg"
@ -65,7 +48,7 @@
<img src="media/thumbs/photos/port-douglas2.jpg"
width="120"
height="120"
alt="port-douglas2.jpg" />
alt="" />
</a>
</li>
</ul>

View File

@ -13,30 +13,13 @@
<body>
<header>
<a href="index.html">
<h1>Photo</h1>
<h2>gallery</h2>
</a>
</header>
<nav>
<ul>
<li >
<a href="photos.html">photos</a>
</li>
<li >
<a href="videos.html">videos</a>
</li>
<li >
<a href="captions.html">captions</a>
</li>
<li class="active">
<a href="rotations.html">rotations</a>
</li>
</ul>
Breadcrumbs
</nav>
<ul id="albums">
</ul>
<ul id="gallery">
<li data-src="media/large/rotations/Landscape_1.jpg"
data-sub-html=""
@ -45,7 +28,7 @@
<img src="media/thumbs/rotations/Landscape_1.jpg"
width="120"
height="120"
alt="Landscape_1.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_2.jpg"
@ -55,7 +38,7 @@
<img src="media/thumbs/rotations/Landscape_2.jpg"
width="120"
height="120"
alt="Landscape_2.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_3.jpg"
@ -65,7 +48,7 @@
<img src="media/thumbs/rotations/Landscape_3.jpg"
width="120"
height="120"
alt="Landscape_3.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_4.jpg"
@ -75,7 +58,7 @@
<img src="media/thumbs/rotations/Landscape_4.jpg"
width="120"
height="120"
alt="Landscape_4.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_5.jpg"
@ -85,7 +68,7 @@
<img src="media/thumbs/rotations/Landscape_5.jpg"
width="120"
height="120"
alt="Landscape_5.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_6.jpg"
@ -95,7 +78,7 @@
<img src="media/thumbs/rotations/Landscape_6.jpg"
width="120"
height="120"
alt="Landscape_6.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_7.jpg"
@ -105,7 +88,7 @@
<img src="media/thumbs/rotations/Landscape_7.jpg"
width="120"
height="120"
alt="Landscape_7.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_8.jpg"
@ -115,7 +98,7 @@
<img src="media/thumbs/rotations/Landscape_8.jpg"
width="120"
height="120"
alt="Landscape_8.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_1.jpg"
@ -125,7 +108,7 @@
<img src="media/thumbs/rotations/Portrait_1.jpg"
width="120"
height="120"
alt="Portrait_1.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_2.jpg"
@ -135,7 +118,7 @@
<img src="media/thumbs/rotations/Portrait_2.jpg"
width="120"
height="120"
alt="Portrait_2.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_3.jpg"
@ -145,7 +128,7 @@
<img src="media/thumbs/rotations/Portrait_3.jpg"
width="120"
height="120"
alt="Portrait_3.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_4.jpg"
@ -155,7 +138,7 @@
<img src="media/thumbs/rotations/Portrait_4.jpg"
width="120"
height="120"
alt="Portrait_4.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_5.jpg"
@ -165,7 +148,7 @@
<img src="media/thumbs/rotations/Portrait_5.jpg"
width="120"
height="120"
alt="Portrait_5.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_6.jpg"
@ -175,7 +158,7 @@
<img src="media/thumbs/rotations/Portrait_6.jpg"
width="120"
height="120"
alt="Portrait_6.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_7.jpg"
@ -185,7 +168,7 @@
<img src="media/thumbs/rotations/Portrait_7.jpg"
width="120"
height="120"
alt="Portrait_7.jpg" />
alt="" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_8.jpg"
@ -195,7 +178,7 @@
<img src="media/thumbs/rotations/Portrait_8.jpg"
width="120"
height="120"
alt="Portrait_8.jpg" />
alt="" />
</a>
</li>
</ul>

View File

@ -13,63 +13,46 @@
<body>
<header>
<a href="index.html">
<h1>Photo</h1>
<h2>gallery</h2>
</a>
</header>
<nav>
<ul>
<li >
<a href="photos.html">photos</a>
</li>
<li class="active">
<a href="videos.html">videos</a>
</li>
<li >
<a href="captions.html">captions</a>
</li>
<li >
<a href="rotations.html">rotations</a>
</li>
</ul>
Breadcrumbs
</nav>
<ul id="albums">
</ul>
<ul id="gallery">
<li data-html="#media7"
<li data-html="#media23"
data-poster="media/large/videos/countdown.jpg"
data-download-url="media/large/videos/countdown.mp4">
<a href="media/large/videos/countdown.mp4">
<img src="media/thumbs/videos/countdown.jpg"
width="120"
width=""
height="120"
alt="countdown.mp4" />
alt="" />
</a>
<img class="video-overlay" src="public/play.png" />
</li>
<li data-html="#media8"
<li data-html="#media24"
data-poster="media/large/videos/momentum.jpg"
data-download-url="media/large/videos/momentum.mp4">
<a href="media/large/videos/momentum.mp4">
<img src="media/thumbs/videos/momentum.jpg"
width="120"
width=""
height="120"
alt="momentum.m2ts" />
alt="" />
</a>
<img class="video-overlay" src="public/play.png" />
</li>
</ul>
<div id="videos">
<div id="media7" style="display:none;">
<div id="media23" style="display:none;">
<video class="lg-video-object lg-html5 video-js vjs-default-skin" preload="none" controls>
<source src="media/large/videos/countdown.mp4" type="video/mp4" />
Your browser does not support HTML5 video
</video>
</div>
<div id="media8" style="display:none;">
<div id="media24" style="display:none;">
<video class="lg-video-object lg-html5 video-js vjs-default-skin" preload="none" controls>
<source src="media/large/videos/momentum.mp4" type="video/mp4" />
Your browser does not support HTML5 video

146
docs/index-photos.html Normal file
View File

@ -0,0 +1,146 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>Photo album - photos</title>
<link rel="stylesheet" href="public/reset.css" />
<link rel="stylesheet" href="public/light-gallery/css/lightgallery.css" />
<link rel="stylesheet" href="public/video-js.css" />
<link rel="stylesheet" href="public/theme.css" />
</head>
<body>
<header>
<h1>Photo album</h1>
<h2></h2>
</header>
<section id="sidebar">
<nav>
<!-- This album -->
<a href="index.html">
Home<span class="count">24</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-photos.html">
-
photos<span class="count">3</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-videos.html">
-
videos<span class="count">2</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-captions.html">
-
captions<span class="count">3</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-rotations.html">
-
rotations<span class="count">16</span>
</a>
<!-- And nested album -->
</nav>
</section>
<section id="content">
<nav class="breadcrumbs">
<a class="breadcrumb-item" href="index.html">Home </a><span class="breadcrumb-item active">photos</span>
</nav>
<ul id="albums">
</ul>
<ul id="gallery">
<li data-src="media/large/photos/port-stephens.jpg"
data-sub-html=""
data-download-url="media/large/photos/port-stephens.jpg">
<a href="media/large/photos/port-stephens.jpg">
<img src="media/thumbs/photos/port-stephens.jpg"
width="120"
height="120"
alt="port-stephens.jpg" />
</a>
</li>
<li data-src="media/large/photos/port-douglas1.jpg"
data-sub-html=""
data-download-url="media/large/photos/port-douglas1.jpg">
<a href="media/large/photos/port-douglas1.jpg">
<img src="media/thumbs/photos/port-douglas1.jpg"
width="120"
height="120"
alt="port-douglas1.jpg" />
</a>
</li>
<li data-src="media/large/photos/port-douglas2.jpg"
data-sub-html=""
data-download-url="media/large/photos/port-douglas2.jpg">
<a href="media/large/photos/port-douglas2.jpg">
<img src="media/thumbs/photos/port-douglas2.jpg"
width="120"
height="120"
alt="port-douglas2.jpg" />
</a>
</li>
</ul>
<div id="videos">
</div>
</section>
<!-- jQuery -->
<script src="public/jquery.min.js"></script>
<!-- VideoJS -->
<script src="public/video.js"></script>
<!-- LightGallery -->
<script src="public/light-gallery/js/lightgallery.js"></script>
<script src="public/light-gallery/js/lg-autoplay.js"></script>
<script src="public/light-gallery/js/lg-pager.js"></script>
<script src="public/light-gallery/js/lg-thumbnail.js"></script>
<script src="public/light-gallery/js/lg-video.js"></script>
<script>
$(document).ready(function() {
$("#gallery").lightGallery({
thumbWidth: 80,
controls: true,
loop : false,
download: true,
counter: true,
videojs: true
});
});
</script>
</body>
</html>

276
docs/index-rotations.html Normal file
View File

@ -0,0 +1,276 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>Photo album - rotations</title>
<link rel="stylesheet" href="public/reset.css" />
<link rel="stylesheet" href="public/light-gallery/css/lightgallery.css" />
<link rel="stylesheet" href="public/video-js.css" />
<link rel="stylesheet" href="public/theme.css" />
</head>
<body>
<header>
<h1>Photo album</h1>
<h2></h2>
</header>
<section id="sidebar">
<nav>
<!-- This album -->
<a href="index.html">
Home<span class="count">24</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-photos.html">
-
photos<span class="count">3</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-videos.html">
-
videos<span class="count">2</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-captions.html">
-
captions<span class="count">3</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-rotations.html">
-
rotations<span class="count">16</span>
</a>
<!-- And nested album -->
</nav>
</section>
<section id="content">
<nav class="breadcrumbs">
<a class="breadcrumb-item" href="index.html">Home </a><span class="breadcrumb-item active">rotations</span>
</nav>
<ul id="albums">
</ul>
<ul id="gallery">
<li data-src="media/large/rotations/Landscape_1.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Landscape_1.jpg">
<a href="media/large/rotations/Landscape_1.jpg">
<img src="media/thumbs/rotations/Landscape_1.jpg"
width="120"
height="120"
alt="Landscape_1.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_2.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Landscape_2.jpg">
<a href="media/large/rotations/Landscape_2.jpg">
<img src="media/thumbs/rotations/Landscape_2.jpg"
width="120"
height="120"
alt="Landscape_2.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_3.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Landscape_3.jpg">
<a href="media/large/rotations/Landscape_3.jpg">
<img src="media/thumbs/rotations/Landscape_3.jpg"
width="120"
height="120"
alt="Landscape_3.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_4.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Landscape_4.jpg">
<a href="media/large/rotations/Landscape_4.jpg">
<img src="media/thumbs/rotations/Landscape_4.jpg"
width="120"
height="120"
alt="Landscape_4.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_5.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Landscape_5.jpg">
<a href="media/large/rotations/Landscape_5.jpg">
<img src="media/thumbs/rotations/Landscape_5.jpg"
width="120"
height="120"
alt="Landscape_5.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_6.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Landscape_6.jpg">
<a href="media/large/rotations/Landscape_6.jpg">
<img src="media/thumbs/rotations/Landscape_6.jpg"
width="120"
height="120"
alt="Landscape_6.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_7.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Landscape_7.jpg">
<a href="media/large/rotations/Landscape_7.jpg">
<img src="media/thumbs/rotations/Landscape_7.jpg"
width="120"
height="120"
alt="Landscape_7.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Landscape_8.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Landscape_8.jpg">
<a href="media/large/rotations/Landscape_8.jpg">
<img src="media/thumbs/rotations/Landscape_8.jpg"
width="120"
height="120"
alt="Landscape_8.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_1.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Portrait_1.jpg">
<a href="media/large/rotations/Portrait_1.jpg">
<img src="media/thumbs/rotations/Portrait_1.jpg"
width="120"
height="120"
alt="Portrait_1.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_2.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Portrait_2.jpg">
<a href="media/large/rotations/Portrait_2.jpg">
<img src="media/thumbs/rotations/Portrait_2.jpg"
width="120"
height="120"
alt="Portrait_2.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_3.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Portrait_3.jpg">
<a href="media/large/rotations/Portrait_3.jpg">
<img src="media/thumbs/rotations/Portrait_3.jpg"
width="120"
height="120"
alt="Portrait_3.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_4.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Portrait_4.jpg">
<a href="media/large/rotations/Portrait_4.jpg">
<img src="media/thumbs/rotations/Portrait_4.jpg"
width="120"
height="120"
alt="Portrait_4.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_5.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Portrait_5.jpg">
<a href="media/large/rotations/Portrait_5.jpg">
<img src="media/thumbs/rotations/Portrait_5.jpg"
width="120"
height="120"
alt="Portrait_5.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_6.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Portrait_6.jpg">
<a href="media/large/rotations/Portrait_6.jpg">
<img src="media/thumbs/rotations/Portrait_6.jpg"
width="120"
height="120"
alt="Portrait_6.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_7.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Portrait_7.jpg">
<a href="media/large/rotations/Portrait_7.jpg">
<img src="media/thumbs/rotations/Portrait_7.jpg"
width="120"
height="120"
alt="Portrait_7.jpg" />
</a>
</li>
<li data-src="media/large/rotations/Portrait_8.jpg"
data-sub-html=""
data-download-url="media/large/rotations/Portrait_8.jpg">
<a href="media/large/rotations/Portrait_8.jpg">
<img src="media/thumbs/rotations/Portrait_8.jpg"
width="120"
height="120"
alt="Portrait_8.jpg" />
</a>
</li>
</ul>
<div id="videos">
</div>
</section>
<!-- jQuery -->
<script src="public/jquery.min.js"></script>
<!-- VideoJS -->
<script src="public/video.js"></script>
<!-- LightGallery -->
<script src="public/light-gallery/js/lightgallery.js"></script>
<script src="public/light-gallery/js/lg-autoplay.js"></script>
<script src="public/light-gallery/js/lg-pager.js"></script>
<script src="public/light-gallery/js/lg-thumbnail.js"></script>
<script src="public/light-gallery/js/lg-video.js"></script>
<script>
$(document).ready(function() {
$("#gallery").lightGallery({
thumbWidth: 80,
controls: true,
loop : false,
download: true,
counter: true,
videojs: true
});
});
</script>
</body>
</html>

150
docs/index-videos.html Normal file
View File

@ -0,0 +1,150 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>Photo album - videos</title>
<link rel="stylesheet" href="public/reset.css" />
<link rel="stylesheet" href="public/light-gallery/css/lightgallery.css" />
<link rel="stylesheet" href="public/video-js.css" />
<link rel="stylesheet" href="public/theme.css" />
</head>
<body>
<header>
<h1>Photo album</h1>
<h2></h2>
</header>
<section id="sidebar">
<nav>
<!-- This album -->
<a href="index.html">
Home<span class="count">24</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-photos.html">
-
photos<span class="count">3</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-videos.html">
-
videos<span class="count">2</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-captions.html">
-
captions<span class="count">3</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-rotations.html">
-
rotations<span class="count">16</span>
</a>
<!-- And nested album -->
</nav>
</section>
<section id="content">
<nav class="breadcrumbs">
<a class="breadcrumb-item" href="index.html">Home </a><span class="breadcrumb-item active">videos</span>
</nav>
<ul id="albums">
</ul>
<ul id="gallery">
<li data-html="#media23"
data-poster="media/large/videos/countdown.jpg"
data-download-url="">
<a href="">
<img src="media/thumbs/videos/countdown.jpg"
width=""
height="120"
alt="countdown.mp4" />
</a>
<img class="video-overlay" src="public/play.png" />
</li>
<li data-html="#media24"
data-poster="media/large/videos/momentum.jpg"
data-download-url="">
<a href="">
<img src="media/thumbs/videos/momentum.jpg"
width=""
height="120"
alt="momentum.m2ts" />
</a>
<img class="video-overlay" src="public/play.png" />
</li>
</ul>
<div id="videos">
<div id="media23" style="display:none;">
<video class="lg-video-object lg-html5 video-js vjs-default-skin" preload="none" controls>
<source src="media/large/videos/countdown.mp4" type="video/mp4" />
Your browser does not support HTML5 video
</video>
</div>
<div id="media24" style="display:none;">
<video class="lg-video-object lg-html5 video-js vjs-default-skin" preload="none" controls>
<source src="media/large/videos/momentum.mp4" type="video/mp4" />
Your browser does not support HTML5 video
</video>
</div>
</div>
</section>
<!-- jQuery -->
<script src="public/jquery.min.js"></script>
<!-- VideoJS -->
<script src="public/video.js"></script>
<!-- LightGallery -->
<script src="public/light-gallery/js/lightgallery.js"></script>
<script src="public/light-gallery/js/lg-autoplay.js"></script>
<script src="public/light-gallery/js/lg-pager.js"></script>
<script src="public/light-gallery/js/lg-thumbnail.js"></script>
<script src="public/light-gallery/js/lg-video.js"></script>
<script>
$(document).ready(function() {
$("#gallery").lightGallery({
thumbWidth: 80,
controls: true,
loop : false,
download: true,
counter: true,
videojs: true
});
});
</script>
</body>
</html>

View File

@ -4,68 +4,151 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>Photo gallery</title>
<title>Photo album - Home</title>
<link rel="stylesheet" href="public/reset.css" />
<link rel="stylesheet" href="public/light-gallery/css/lightgallery.css" />
<link rel="stylesheet" href="public/video-js.css" />
<link rel="stylesheet" href="public/theme.css" />
</head>
<body>
<header>
<h1>Photo</h1>
<h2>gallery</h2>
<h1>Photo album</h1>
<h2></h2>
</header>
<ul id="galleries">
<li>
<a href="photos.html">
<h3>photos</h3>
<div class="meta">
3 photos<br />
26 Aug 12 - 31 Oct 13
</div>
<ul class="grid">
<li><img src="media/thumbs/photos/port-stephens.jpg" /></li><li><img src="media/thumbs/photos/port-douglas1.jpg" /></li><li><img src="media/thumbs/photos/port-douglas2.jpg" /></li><li><img src="public/missing.png" /></li>
</ul>
<section id="sidebar">
<nav>
<!-- This album -->
<a href="index.html">
Home<span class="count">24</span>
</a>
</li>
<li>
<a href="videos.html">
<h3>videos</h3>
<div class="meta">
2 videos<br />
18 Apr 14 - 2 Dec 14
</div>
<ul class="grid">
<li><img src="media/thumbs/videos/countdown.jpg" /></li><li><img src="media/thumbs/videos/momentum.jpg" /></li><li><img src="public/missing.png" /></li><li><img src="public/missing.png" /></li>
</ul>
</a>
</li>
<li>
<a href="captions.html">
<h3>captions</h3>
<div class="meta">
3 photos<br />
22 Sep 15 - 22 Sep 15
</div>
<ul class="grid">
<li><img src="media/thumbs/captions/sunset.jpg" /></li><li><img src="media/thumbs/captions/tree.jpg" /></li><li><img src="media/thumbs/captions/water.jpg" /></li><li><img src="public/missing.png" /></li>
</ul>
</a>
</li>
<li>
<a href="rotations.html">
<h3>rotations</h3>
<div class="meta">
16 photos<br />
8 Oct 16 - 8 Oct 16
</div>
<ul class="grid">
<li><img src="media/thumbs/rotations/Landscape_1.jpg" /></li><li><img src="media/thumbs/rotations/Landscape_2.jpg" /></li><li><img src="media/thumbs/rotations/Landscape_3.jpg" /></li><li><img src="media/thumbs/rotations/Landscape_4.jpg" /></li>
</ul>
</a>
</li>
</ul>
<!-- And nested album -->
<!-- This album -->
<a href="index-photos.html">
-
photos<span class="count">3</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-videos.html">
-
videos<span class="count">2</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-captions.html">
-
captions<span class="count">3</span>
</a>
<!-- And nested album -->
<!-- This album -->
<a href="index-rotations.html">
-
rotations<span class="count">16</span>
</a>
<!-- And nested album -->
</nav>
</section>
<section id="content">
<nav class="breadcrumbs">
<span class="breadcrumb-item active">Home</span>
</nav>
<ul id="albums">
<li>
<a href="index-photos.html">
<ul class="grid clearfix"><li><img src="media/thumbs/photos/port-stephens.jpg" /></li><li><img src="media/thumbs/photos/port-douglas1.jpg" /></li> </ul>
<h3>photos</h3>
<div class="meta">
3 photos<br />
26 Aug 2012 - 31 Oct 2013
</div>
</a>
</li>
<li>
<a href="index-videos.html">
<ul class="grid clearfix"><li><img src="media/thumbs/videos/countdown.jpg" /></li><li><img src="media/thumbs/videos/momentum.jpg" /></li> </ul>
<h3>videos</h3>
<div class="meta">
2 videos<br />
18 Apr 2014 - 02 Dec 2014
</div>
</a>
</li>
<li>
<a href="index-captions.html">
<ul class="grid clearfix"><li><img src="media/thumbs/captions/sunset.jpg" /></li><li><img src="media/thumbs/captions/tree.jpg" /></li> </ul>
<h3>captions</h3>
<div class="meta">
3 photos<br />
22 Sep 2015 - 22 Sep 2015
</div>
</a>
</li>
<li>
<a href="index-rotations.html">
<ul class="grid clearfix"><li><img src="media/thumbs/rotations/Landscape_1.jpg" /></li><li><img src="media/thumbs/rotations/Landscape_2.jpg" /></li> </ul>
<h3>rotations</h3>
<div class="meta">
16 photos<br />
09 Oct 2016 - 09 Oct 2016
</div>
</a>
</li>
</ul>
<ul id="gallery">
</ul>
<div id="videos">
</div>
</section>
<!-- jQuery -->
<script src="public/jquery.min.js"></script>
<!-- VideoJS -->
<script src="public/video.js"></script>
<!-- LightGallery -->
<script src="public/light-gallery/js/lightgallery.js"></script>
<script src="public/light-gallery/js/lg-autoplay.js"></script>
<script src="public/light-gallery/js/lg-pager.js"></script>
<script src="public/light-gallery/js/lg-thumbnail.js"></script>
<script src="public/light-gallery/js/lg-video.js"></script>
<script>
$(document).ready(function() {
$("#gallery").lightGallery({
thumbWidth: 80,
controls: true,
loop : false,
download: true,
counter: true,
videojs: true
});
});
</script>
</body>

View File

@ -50,6 +50,134 @@
"orientation": 1
}
},
"rotations/Landscape_1.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 1
}
},
"rotations/Landscape_2.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 2
}
},
"rotations/Landscape_3.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 3
}
},
"rotations/Landscape_4.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 4
}
},
"rotations/Landscape_5.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 5
}
},
"rotations/Landscape_6.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 6
}
},
"rotations/Landscape_7.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 7
}
},
"rotations/Landscape_8.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 8
}
},
"rotations/Portrait_1.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 1
}
},
"rotations/Portrait_2.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 2
}
},
"rotations/Portrait_3.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 3
}
},
"rotations/Portrait_4.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 4
}
},
"rotations/Portrait_5.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 5
}
},
"rotations/Portrait_6.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 6
}
},
"rotations/Portrait_7.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 7
}
},
"rotations/Portrait_8.jpg": {
"fileDate": 1475977293000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 8
}
},
"videos/countdown.mp4": {
"fileDate": 1397816697000,
"mediaType": "video",
@ -66,133 +194,5 @@
"orientation": null,
"caption": null
}
},
"rotations/Landscape_1.jpg": {
"fileDate": 1475923610000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 1
}
},
"rotations/Landscape_2.jpg": {
"fileDate": 1475923617000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 2
}
},
"rotations/Landscape_3.jpg": {
"fileDate": 1475923621000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 3
}
},
"rotations/Landscape_4.jpg": {
"fileDate": 1475923625000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 4
}
},
"rotations/Landscape_5.jpg": {
"fileDate": 1475923628000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 5
}
},
"rotations/Landscape_6.jpg": {
"fileDate": 1475923634000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 6
}
},
"rotations/Landscape_7.jpg": {
"fileDate": 1475923636000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 7
}
},
"rotations/Landscape_8.jpg": {
"fileDate": 1475923640000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 8
}
},
"rotations/Portrait_1.jpg": {
"fileDate": 1475923644000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 1
}
},
"rotations/Portrait_2.jpg": {
"fileDate": 1475923647000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 2
}
},
"rotations/Portrait_3.jpg": {
"fileDate": 1475923650000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 3
}
},
"rotations/Portrait_4.jpg": {
"fileDate": 1475923653000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 4
}
},
"rotations/Portrait_5.jpg": {
"fileDate": 1475923659000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 5
}
},
"rotations/Portrait_6.jpg": {
"fileDate": 1475923663000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 6
}
},
"rotations/Portrait_7.jpg": {
"fileDate": 1475923666000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 7
}
},
"rotations/Portrait_8.jpg": {
"fileDate": 1475923670000,
"mediaType": "photo",
"exif": {
"date": null,
"orientation": 8
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -3,25 +3,64 @@
-moz-box-sizing: border-box;
}
.clearfix:after {
content: " ";
display: block;
clear: both;
}
html, body {
padding: 0;
margin: 0;
}
body {
border-top: 5px solid #33609c;
font-family: 'Open Sans', sans-serif;
font-size: 16px;
font-weight: lighter;
margin: 0 1em;
padding: 0 1em;
-webkit-font-smoothing: antialiased;
}
#sidebar nav {
background: #fafafa;
border-right: 1px solid #ddd;
height: 100%;
padding-bottom: 10em;
overflow-x: hidden;
overflow-y: scroll;
position: fixed;
width: 16em;
}
#sidebar a {
display: block;
padding: 0.8em 1em;
border-bottom: 1px solid #e3e3e3;
}
#sidebar a:hover {
background-color: #fff;
}
#sidebar .count {
background-color: #fcfcfc;
border: 1px solid #eee;
border-radius: 0.4em;
color: #999;
float: right;
font-size: 0.7em;
margin-top: -0.2em;
padding: 0.4em;
}
#content {
margin-left: 16em;
}
header {
font-size: 2em;
padding: 1em 0;
margin-bottom: 0.5em;
border-bottom: 1px solid #eee;
font-size: 1.8em;
padding: 1em;
}
h1 {
@ -35,85 +74,82 @@ h2 {
display: inline-block;
}
h3 {
color: #33609c;
margin-bottom: 0.1em;
font-size: 1.3em;
}
a {
text-decoration: none;
}
nav {
border-top: 1px solid #bbb;
border-bottom: 1px solid #bbb;
margin-bottom: 2.3em;
padding: 1em 0;
nav.breadcrumbs {
background-color: #fafafa;
border-bottom: 1px solid #eee;
margin-bottom: 2em;
padding: 0.8em 0 0.8em 2em;
}
nav li {
display: inline-block;
nav.breadcrumbs a, nav span {
display: inline;
}
nav a {
color: #666;
display: inline-block;
min-width: 7em;
padding: 0.4em 1em;
nav.breadcrumbs a {
color: #014c8c;
text-decoration: none;
}
nav li.active {
background-color: #bbb;
nav.breadcrumbs a:after {
content: ' / '
}
nav li.active a {
color: #fff;
font-weight: bold;
}
nav li:not(.active):hover {
background-color: #eee;
}
#galleries a {
display: inline-block;
}
#galleries .meta {
font-size: 0.9em;
width: 100%;
margin: 0.5em 0;
nav.breadcrumbs span {
color: #666;
line-height: 1.2em;
}
#galleries > li {
#albums, #gallery {
margin: 2em;
}
#albums a {
background-color: #f9f9f9;
border-bottom: 1px solid #33609c;
display: inline-block;
padding: 0.7em;
}
#albums h3 {
color: #33609c;
margin: 0.7em;
font-size: 1em;
text-align: center;
}
#albums .meta {
color: #666;
font-size: 0.9em;
line-height: 1.2em;
margin: 0.5em 0;
text-align: center;
width: 100%;
}
#albums > li {
display: inline-block;
margin-right: 2em;
margin-bottom: 3em;
}
#galleries .grid {
#albums .grid {
width: 200px;
}
#galleries .grid li {
#albums .grid li {
float: left;
padding: 0 0.2em 0.2em 0;
width: 50%;
}
#galleries .grid img {
#albums .grid img {
display: block;
width: 100%;
}
#gallery {
margin-bottom: 3em;
}
#gallery li {
float: left;
margin-right: 0.4em;

5
docs/public/video-js.css Normal file

File diff suppressed because one or more lines are too long

203
docs/public/video.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
{
"input": "example/media",
"output": "docs",
"title": "Photo gallery",
"title": "Photo album",
"thumb-size": 120,
"large-size": 400,
"original-photos": false,

View File

@ -19,6 +19,7 @@
"url": "https://github.com/rprieto/thumbsup.git"
},
"scripts": {
"test": "mocha",
"clean": "rm -rf docs/*",
"example": "node bin/thumbsup --config example.json",
"open": "open docs/index.html",
@ -43,6 +44,9 @@
},
"devDependencies": {
"injectmd": "^1.0.0",
"markdown-toc": "^0.12.5"
"markdown-toc": "^0.12.5",
"mocha": "^3.1.0",
"should": "^11.1.0",
"sinon": "^1.17.6"
}
}

File diff suppressed because one or more lines are too long

View File

@ -3,25 +3,64 @@
-moz-box-sizing: border-box;
}
.clearfix:after {
content: " ";
display: block;
clear: both;
}
html, body {
padding: 0;
margin: 0;
}
body {
border-top: 5px solid #33609c;
font-family: 'Open Sans', sans-serif;
font-size: 16px;
font-weight: lighter;
margin: 0 1em;
padding: 0 1em;
-webkit-font-smoothing: antialiased;
}
#sidebar nav {
background: #fafafa;
border-right: 1px solid #ddd;
height: 100%;
padding-bottom: 10em;
overflow-x: hidden;
overflow-y: scroll;
position: fixed;
width: 16em;
}
#sidebar a {
display: block;
padding: 0.8em 1em;
border-bottom: 1px solid #e3e3e3;
}
#sidebar a:hover {
background-color: #fff;
}
#sidebar .count {
background-color: #fcfcfc;
border: 1px solid #eee;
border-radius: 0.4em;
color: #999;
float: right;
font-size: 0.7em;
margin-top: -0.2em;
padding: 0.4em;
}
#content {
margin-left: 16em;
}
header {
font-size: 2em;
padding: 1em 0;
margin-bottom: 0.5em;
border-bottom: 1px solid #eee;
font-size: 1.8em;
padding: 1em;
}
h1 {
@ -35,85 +74,82 @@ h2 {
display: inline-block;
}
h3 {
color: #33609c;
margin-bottom: 0.1em;
font-size: 1.3em;
}
a {
text-decoration: none;
}
nav {
border-top: 1px solid #bbb;
border-bottom: 1px solid #bbb;
margin-bottom: 2.3em;
padding: 1em 0;
nav.breadcrumbs {
background-color: #fafafa;
border-bottom: 1px solid #eee;
margin-bottom: 2em;
padding: 0.8em 0 0.8em 2em;
}
nav li {
display: inline-block;
nav.breadcrumbs a, nav span {
display: inline;
}
nav a {
color: #666;
display: inline-block;
min-width: 7em;
padding: 0.4em 1em;
nav.breadcrumbs a {
color: #014c8c;
text-decoration: none;
}
nav li.active {
background-color: #bbb;
nav.breadcrumbs a:after {
content: ' / '
}
nav li.active a {
color: #fff;
font-weight: bold;
}
nav li:not(.active):hover {
background-color: #eee;
}
#galleries a {
display: inline-block;
}
#galleries .meta {
font-size: 0.9em;
width: 100%;
margin: 0.5em 0;
nav.breadcrumbs span {
color: #666;
line-height: 1.2em;
}
#galleries > li {
#albums, #gallery {
margin: 2em;
}
#albums a {
background-color: #f9f9f9;
border-bottom: 1px solid #33609c;
display: inline-block;
padding: 0.7em;
}
#albums h3 {
color: #33609c;
margin: 0.7em;
font-size: 1em;
text-align: center;
}
#albums .meta {
color: #666;
font-size: 0.9em;
line-height: 1.2em;
margin: 0.5em 0;
text-align: center;
width: 100%;
}
#albums > li {
display: inline-block;
margin-right: 2em;
margin-bottom: 3em;
}
#galleries .grid {
#albums .grid {
width: 200px;
}
#galleries .grid li {
#albums .grid li {
float: left;
padding: 0 0.2em 0.2em 0;
width: 50%;
}
#galleries .grid img {
#albums .grid img {
display: block;
width: 100%;
}
#gallery {
margin-bottom: 3em;
}
#gallery li {
float: left;
margin-right: 0.4em;

5
public/video-js.css Normal file

File diff suppressed because one or more lines are too long

203
public/video.js Normal file

File diff suppressed because one or more lines are too long

BIN
screenshot-albums.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

BIN
screenshot-files.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

9
src/collection.js Normal file
View File

@ -0,0 +1,9 @@
var File = require('./file');
exports.fromMetadata = function(metadata) {
return {
files: Object.keys(metadata).map(function(filepath) {
return new File(filepath, metadata[filepath]);
})
}
};

39
src/file.js Normal file
View File

@ -0,0 +1,39 @@
var path = require('path');
var index = 0;
function File(filepath, metadata) {
this.id = ++index;
this.filepath = filepath;
this.filename = path.basename(filepath);
this.date = new Date(metadata.exif.date || metadata.fileDate);
this.caption = metadata.exif.caption;
this.isVideo = (metadata.mediaType === 'video');
this.urls = urls(filepath, metadata.mediaType);
}
function urls(filepath, mediaType) {
return (mediaType === 'video') ? videoUrls(filepath) : photoUrls(filepath);
}
function videoUrls(filepath) {
return {
thumb: 'media/thumbs/' + ext(filepath, 'jpg'),
poster: 'media/large/' + ext(filepath, 'jpg'),
video: 'media/large/' + ext(filepath, 'mp4'),
original: 'media/original/' + filepath
};
}
function photoUrls(filepath) {
return {
thumb: 'media/thumbs/' + filepath,
large: 'media/large/' + filepath,
original: 'media/original/' + filepath
};
}
function ext(file, ext) {
return file.replace(/\.[a-z0-9]+$/i, '.' + ext);
}
module.exports = File;

View File

@ -4,7 +4,8 @@ var async = require('async');
var make = require('./utils/make');
var metadata = require('./input/metadata');
var thumbs = require('./output-media/thumbs');
var website = require('./output-website/generator');
var website = require('./output-website/website');
var collection = require('./collection');
exports.build = function(opts) {
@ -13,7 +14,8 @@ exports.build = function(opts) {
fs.mkdirpSync(opts.output);
var media = path.join(opts.output, 'media');
var meta = null;
var meta = null;
var allFiles = collection.fromMetadata({});
function buildStep(options) {
return function(callback) {
@ -34,6 +36,7 @@ exports.build = function(opts) {
function updateMetadata(callback) {
metadata.update(opts, function(err, data) {
meta = data;
allFiles = collection.fromMetadata(data);
callback(err);
});
},
@ -90,7 +93,7 @@ exports.build = function(opts) {
}),
function staticWebsite(callback) {
website.build(meta, opts, callback);
website.build(allFiles, opts, callback);
}
], finish);

105
src/output-website/album.js Normal file
View File

@ -0,0 +1,105 @@
var _ = require('lodash');
var index = 0;
// number of images to show in the album preview grid
var PREVIEW_COUNT = 2;
var SORT_ALBUMS_BY = {
title: function(album) { return album.title; },
date: function(album) { return album.stats.fromDate; }
};
var SORT_MEDIA_BY = {
filename: function(file) { return file.filename; },
date: function(file) { return file.date; }
};
function Album(opts) {
if (typeof opts === 'string') opts = { title: opts };
this.title = opts.title || ('Album ' + index++);
this.filename = sanitise(this.title);
this.files = opts.files || [];
this.albums = opts.albums || [];
this.depth = 0;
this.stats = null;
this.previews = null;
}
Album.prototype.finalize = function(options) {
options = _.defaults(options, {
sortAlbumsBy: 'date',
sortMediaBy: 'date'
});
// lock all nested albums first (recursive)
// and set a nested filename
for (var i = 0; i < this.albums.length; ++i) {
this.albums[i].filename = this.filename + '-' + this.albums[i].filename;
this.albums[i].depth = this.depth + 1;
this.albums[i].finalize();
}
this.calculateStats();
this.calculateSummary();
this.sort(options);
this.pickPreviews();
};
Album.prototype.calculateStats = function() {
// nested albums
var nestedPhotos = _.map(this.albums, 'stats.photos');
var nestedVideos = _.map(this.albums, 'stats.videos');
var nestedFromDates = _.map(this.albums, 'stats.fromDate');
var nestedToDates = _.map(this.albums, 'stats.toDate');
// current level
var currentPhotos = _.filter(this.files, {isVideo: false}).length;
var currentVideos = _.filter(this.files, {isVideo: true}).length;
var currentFromDate = _.map(this.files, 'date');
var currentToDate = _.map(this.files, 'date');
// aggregate all stats
this.stats = {
albums: this.albums.length,
photos: _.sum(_.compact(_.concat(nestedPhotos, currentPhotos))) || 0,
videos: _.sum(_.compact(_.concat(nestedVideos, currentVideos))) || 0,
fromDate: _.min(_.compact(_.concat(nestedFromDates, currentFromDate))),
toDate: _.max(_.compact(_.concat(nestedToDates, currentToDate)))
};
this.stats.total = this.stats.photos + this.stats.videos;
}
Album.prototype.calculateSummary = function() {
var items = [
itemCount(this.stats.albums, 'album'),
itemCount(this.stats.photos, 'photo'),
itemCount(this.stats.videos, 'video')
];
this.summary = _.compact(items).join(', ');
};
Album.prototype.sort = function(options) {
this.files = _.sortBy(this.files, SORT_MEDIA_BY[options.sortMediaBy]);
this.albums = _.sortBy(this.albums, SORT_ALBUMS_BY[options.sortAlbumsBy]);
this.albums.forEach(function(nested) {
nested.sort(options);
});
};
Album.prototype.pickPreviews = function() {
this.previews = this.files.slice(0, PREVIEW_COUNT);
var missing = PREVIEW_COUNT - this.previews.length;
for (var i = 0; i < missing; ++i) {
this.previews.push({
urls: { thumb: 'public/missing.png' }
});
}
};
function sanitise(filename) {
return filename.replace(/[^a-z0-9-_]/ig, '');
}
function itemCount(count, type) {
if (count === 0) return '';
var plural = (count > 1) ? 's' : '';
return '' + count + ' ' + type + plural;
}
module.exports = Album;

View File

@ -0,0 +1,31 @@
var _ = require('lodash');
var path = require('path');
var Album = require('./album');
// for now, a single level of albums by month named "{year}-{month}"
// eventually could support nested albums e.g. "{year}/{month}"
// it could be an option like "format: yyyy/mm"
exports.albums = function(collection, opts) {
var groups = {};
collection.files.forEach(function(file) {
var groupName = exports.format(file.date);
if (!groups.hasOwnProperty(groupName)) {
groups[groupName] = [];
}
groups[groupName].push(file);
});
var albums = _.map(groups, function(val, key) {
return new Album({
title: key,
files: groups[key]
});
})
return albums;
};
exports.format = function(date) {
var year = date.getFullYear().toString();
var month = new String(date.getMonth() + 1);
if (month.length === 1) month = '0' + month;
return year + '-' + month;
};

View File

@ -0,0 +1,24 @@
var _ = require('lodash');
var path = require('path');
var Album = require('./album');
// for now only 1 level of folders,
// e.g. an album might be called "holidays/newyork" or "holidays/tokyo"n
// eventually we could return nested albums as an option
exports.albums = function(collection, opts) {
var folders = {};
collection.files.forEach(function(file) {
var dir = path.dirname(file.filepath);
if (!folders.hasOwnProperty(dir)) {
folders[dir] = [];
}
folders[dir].push(file);
});
var albums = _.map(folders, function(val, key) {
return new Album({
title: key,
files: folders[key]
});
})
return albums;
};

View File

@ -1,77 +0,0 @@
var _ = require('lodash');
var fs = require('fs-extra');
var path = require('path');
var async = require('async');
var pad = require('pad');
var files = require('../utils/files');
var template = require('./template');
var model = require('./model');
var pages = require('./pages');
exports.build = function(metadata, opts, callback) {
var common = pages.common(opts);
function render(filename, templateName, data) {
var fullPath = path.join(opts.output, filename);
var pageData = _.extend(data, common);
var contents = template.render(templateName, pageData);
return function(next) {
fs.writeFile(fullPath, contents, next);
};
}
function website(callback) {
var structure = model.create(metadata, opts);
var homepage = pages.homepage(structure);
var index = opts.index || 'index.html';
var items = [
render(index, 'homepage', homepage)
];
structure.forEach(function(folder, index) {
var gallery = pages.gallery(structure, index);
var page = render(folder.name + '.html', 'gallery', gallery);
items.push(page);
});
async.parallel(items, callback);
}
function lightGallery(callback) {
// note: this module might be deduped
// so we can't assume it's in the local node_modules
var lgPackage = require.resolve('lightgallery/package.json');
var src = path.join(path.dirname(lgPackage), 'dist');
var dest = path.join(opts.output, 'public', 'light-gallery');
fs.copy(src, dest, callback);
}
function support(callback) {
var src = path.join(__dirname, '..', '..', 'public');
var dest = path.join(opts.output, 'public');
fs.copy(src, dest, callback);
}
function customStyle(callback) {
if (opts.css) {
var dest = path.join(opts.output, 'public', path.basename(opts.css));
fs.copy(opts.css, dest, callback);
} else {
callback();
}
}
process.stdout.write(pad('Static website', 20));
async.series([
website,
lightGallery,
support,
customStyle
], function(err) {
console.log('[====================] done');
callback(err);
});
};

View File

@ -1,91 +0,0 @@
var _ = require('lodash');
var fs = require('fs');
var path = require('path');
var glob = require('glob');
/*
In-memory structure of the galleries organised in folders
with relative links to the media, thumbnails, etc...
*/
exports.create = function(metadata, opts) {
var index = 0;
function fileInfo(data, file) {
return {
id: ++index,
date: data.exif.date || data.fileDate,
path: file,
name: path.basename(file),
video: data.mediaType === 'video',
size: opts.thumbSize,
urls: urls(file, data),
caption: data.exif.caption
}
}
function urls(file, data) {
if (data.mediaType === 'video') {
var urls = videoUrls(file);
urls.download = opts.originalVideos ? urls.original : urls.video;
return urls;
} else {
var urls = photoUrls(file);
urls.download = opts.originalPhotos ? urls.original : urls.large;
return urls;
}
}
function videoUrls(file) {
return {
thumb: 'media/thumbs/' + ext(file, 'jpg'),
poster: 'media/large/' + ext(file, 'jpg'),
video: 'media/large/' + ext(file, 'mp4'),
original: 'media/original/' + file
};
}
function photoUrls(file) {
return {
thumb: 'media/thumbs/' + file,
large: 'media/large/' + file,
original: 'media/original/' + file
};
}
function ext(file, ext) {
return file.replace(/\.[a-z0-9]+$/i, '.' + ext);
}
function byFolder(file) {
return path.dirname(file.path);
}
function folderInfo(files, name) {
return {
name: name,
media: files,
url: name + '.html'
};
}
var sortFunctions = {
'name': function(folder) {
return folder.name;
},
'date': function(folder) {
return _(folder.media).sortBy('date').first().date;
}
};
var chosenSort = sortFunctions[opts.sortFolders];
return _(metadata).map(fileInfo)
.sortBy('date')
.groupBy(byFolder)
.map(folderInfo)
.sortBy(chosenSort)
.value();
};

View File

@ -1,75 +0,0 @@
var _ = require('lodash');
var path = require('path');
var moment = require('moment');
/*
Common page data shared by all models
*/
exports.common = function(opts) {
var titleParts = opts.title.split(' ');
return {
css: opts.css ? path.basename(opts.css) : null,
title: titleParts[0],
subtitle: titleParts.slice(1).join(' '),
googleAnalytics: opts.googleAnalytics
};
};
/*
Homepage data
*/
exports.homepage = function(structure) {
var galleries = structure.map(function(folder) {
return {
name: folder.name,
url: folder.name + '.html',
stats: stats(folder.media),
fromDate: date(_.minBy(folder.media, 'date').date),
toDate: date(_.maxBy(folder.media, 'date').date),
grid: grid(folder.media)
};
});
return {
galleries: galleries
};
};
/*
Single gallery page
*/
exports.gallery = function(structure, index) {
var links = structure.map(function(folder, i) {
return {
name: folder.name,
url: folder.name + '.html',
active: (i === index)
};
});
return {
links: links,
gallery: structure[index]
};
};
function stats(media) {
var results = [];
var photos = _.filter(media, {video: false}).length;
var videos = _.filter(media, {video: true}).length;
if (photos > 0) results.push(photos + ' photos');
if (videos > 0) results.push(videos + ' videos');
return results.join(', ');
}
function date(timestamp) {
return moment(timestamp).format('D MMM YY');
}
function grid(media) {
return [
(media.length > 0) ? media[0].urls.thumb : 'public/missing.png',
(media.length > 1) ? media[1].urls.thumb : 'public/missing.png',
(media.length > 2) ? media[2].urls.thumb : 'public/missing.png',
(media.length > 3) ? media[3].urls.thumb : 'public/missing.png'
];
}

View File

@ -1,6 +1,12 @@
var fs = require('fs');
var path = require('path');
var handlebars = require('handlebars');
var moment = require('moment');
var options = {};
var templates = {
'album': compileTemplate('album.hbs')
};
function compileTemplate(hbsFile) {
var src = fs.readFileSync(path.join(__dirname, '..', '..', 'templates', hbsFile));
@ -8,10 +14,41 @@ function compileTemplate(hbsFile) {
}
handlebars.registerPartial('analytics', compileTemplate('analytics.hbs'));
handlebars.registerPartial('sidebar-album', compileTemplate('sidebar-album.hbs'));
var templates = {
'homepage': compileTemplate('homepage.hbs'),
'gallery': compileTemplate('gallery.hbs')
handlebars.registerHelper('date', function(date) {
return moment(date).format('DD MMM YYYY');
});
/*
* Repeat given markup with given times
* provides @index for the repeated iteraction
*/
handlebars.registerHelper("times", function (times, opts) {
var out = "";
var i;
var data = {};
if (times) {
for ( i = 0; i < times; i += 1 ) {
data.index = i;
out += opts.fn(this, {data: data});
}
} else {
out = opts.inverse(this);
}
return out;
});
handlebars.registerHelper('download', function(file) {
if (file.mediaType === 'video') {
return options.originalVideos ? file.urls.original : file.urls.video;
} else {
return options.originalPhotos ? file.urls.original : file.urls.large;
}
});
exports.setOptions = function(opts) {
options = opts;
};
exports.render = function(template, data) {

View File

@ -0,0 +1,101 @@
var _ = require('lodash');
var fs = require('fs-extra');
var path = require('path');
var async = require('async');
var pad = require('pad');
var files = require('../utils/files');
var template = require('./template');
var Album = require('./album');
var byFolder = require('./by-folder');
exports.build = function(collection, opts, callback) {
// set the download link to the right place
template.setOptions({
originalPhotos: opts.originalPhotos,
originalVideos: opts.originalVideos
});
function website(callback) {
// top-level album for the home page
var home = new Album('Home');
home.filename = opts.index || 'index';
// create folder albums
home.albums = byFolder.albums(collection, {});
home.finalize();
// create top level gallery
var gallery = {
home: home,
css: opts.css ? path.basename(opts.css) : null,
title: opts.title,
titleWords: opts.title.split(' '),
thumbSize: opts.thumbSize,
largeSize: opts.largeSize,
googleAnalytics: opts.googleAnalytics
};
// render entire album hierarchy
var tasks = renderAlbum(gallery, [], home);
async.parallel(tasks, callback);
}
function renderAlbum(gallery, breadcrumbs, album) {
// render this album
var thisAlbumTask = renderTemplate(album.filename + '.html', 'album', {
gallery: gallery,
breadcrumbs: breadcrumbs,
album: album
});
var tasks = [thisAlbumTask];
// and all nested albums
album.albums.forEach(function(nested) {
var nestedAlbumsTasks = renderAlbum(gallery, breadcrumbs.concat([album]), nested);
Array.prototype.push.apply(tasks, nestedAlbumsTasks);
});
return tasks;
}
function renderTemplate(filename, templateName, data) {
// render a given HBS template
var fullPath = path.join(opts.output, filename);
var contents = template.render(templateName, data);
return function(next) {
fs.writeFile(fullPath, contents, next);
};
}
function lightGallery(callback) {
// note: this module might be deduped
// so we can't assume it's in the local node_modules
var lgPackage = require.resolve('lightgallery/package.json');
var src = path.join(path.dirname(lgPackage), 'dist');
var dest = path.join(opts.output, 'public', 'light-gallery');
fs.copy(src, dest, callback);
}
function support(callback) {
var src = path.join(__dirname, '..', '..', 'public');
var dest = path.join(opts.output, 'public');
fs.copy(src, dest, callback);
}
function customStyle(callback) {
if (opts.css) {
var dest = path.join(opts.output, 'public', path.basename(opts.css));
fs.copy(opts.css, dest, callback);
} else {
callback();
}
}
process.stdout.write(pad('Static website', 20));
async.series([
website,
lightGallery,
support,
customStyle
], function(err) {
console.log('[====================] done');
callback(err);
});
};

131
templates/album.hbs Normal file
View File

@ -0,0 +1,131 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>{{gallery.title}} - {{album.title}}</title>
<link rel="stylesheet" href="public/reset.css" />
<link rel="stylesheet" href="public/light-gallery/css/lightgallery.css" />
<link rel="stylesheet" href="public/video-js.css" />
<link rel="stylesheet" href="public/theme.css" />
{{#if gallery.css}}
<link rel="stylesheet" href="public/{{gallery.css}}" />
{{/if}}
</head>
<body>
<header>
<h1>{{gallery.title}}</h1>
<h2>{{gallery.subtitle}}</h2>
</header>
<section id="sidebar">
<nav>
{{> sidebar-album gallery.home }}
</nav>
</section>
<section id="content">
<nav class="breadcrumbs">
{{#each breadcrumbs~}}
<a class="breadcrumb-item" href="{{filename}}.html">{{title}} </a>
{{~/each~}}
<span class="breadcrumb-item active">{{album.title}}</span>
</nav>
<ul id="albums">
{{#each album.albums}}
<li>
<a href="{{filename}}.html">
<ul class="grid clearfix">
{{~#each previews ~}}
<li><img src="{{this.urls.thumb}}" /></li>
{{~/each}}
</ul>
<h3>{{title}}</h3>
<div class="meta">
{{summary}}<br />
{{{date stats.fromDate}}} - {{{date stats.toDate}}}
</div>
</a>
</li>
{{/each}}
</ul>
<ul id="gallery">
{{#each album.files}}
{{#if isVideo}}
<li data-html="#media{{id}}"
data-poster="{{urls.poster}}"
data-download-url="{{{download this}}}">
<a href="{{{download this}}}">
<img src="{{urls.thumb}}"
width="{{../gallery.thumbsSize}}"
height="{{../gallery.thumbSize}}"
alt="{{filename}}" />
</a>
<img class="video-overlay" src="public/play.png" />
</li>
{{else}}
<li data-src="{{urls.large}}"
data-sub-html="{{caption}}"
data-download-url="{{{download this}}}">
<a href="{{{download this}}}">
<img src="{{urls.thumb}}"
width="{{../gallery.thumbSize}}"
height="{{../gallery.thumbSize}}"
alt="{{filename}}" />
</a>
</li>
{{/if}}
{{/each}}
</ul>
<div id="videos">
{{#each album.files}}
{{#if isVideo}}
<div id="media{{id}}" style="display:none;">
<video class="lg-video-object lg-html5 video-js vjs-default-skin" preload="none" controls>
<source src="{{urls.video}}" type="video/mp4" />
Your browser does not support HTML5 video
</video>
</div>
{{/if}}
{{/each}}
</div>
</section>
<!-- jQuery -->
<script src="public/jquery.min.js"></script>
<!-- VideoJS -->
<script src="public/video.js"></script>
<!-- LightGallery -->
<script src="public/light-gallery/js/lightgallery.js"></script>
<script src="public/light-gallery/js/lg-autoplay.js"></script>
<script src="public/light-gallery/js/lg-pager.js"></script>
<script src="public/light-gallery/js/lg-thumbnail.js"></script>
<script src="public/light-gallery/js/lg-video.js"></script>
<script>
$(document).ready(function() {
$("#gallery").lightGallery({
thumbWidth: 80,
controls: true,
loop : false,
download: true,
counter: true,
videojs: true
});
});
</script>
{{> analytics}}
</body>
</html>

View File

@ -1,4 +1,4 @@
{{#if googleAnalytics}}
{{#if gallery.googleAnalytics}}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){

View File

@ -1,107 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>{{gallery.name}}</title>
<link rel="stylesheet" href="public/reset.css" />
<link rel="stylesheet" href="public/light-gallery/css/lightgallery.css" />
<link rel="stylesheet" href="http://vjs.zencdn.net/4.12/video-js.css" />
<link rel="stylesheet" href="public/theme.css" />
{{#if css}}
<link rel="stylesheet" href="public/{{css}}" />
{{/if}}
</head>
<body>
<header>
<a href="index.html">
<h1>{{title}}</h1>
<h2>{{subtitle}}</h2>
</a>
</header>
<nav>
<ul>
{{#each links}}
<li {{#if active}}class="active"{{/if}}>
<a href="{{url}}">{{name}}</a>
</li>
{{/each}}
</ul>
</nav>
<ul id="gallery">
{{#each gallery.media}}
{{#if video}}
<li data-html="#media{{id}}"
data-poster="{{urls.poster}}"
data-download-url="{{urls.download}}">
<a href="{{urls.download}}">
<img src="{{urls.thumb}}"
width="{{size}}"
height="{{size}}"
alt="{{name}}" />
</a>
<img class="video-overlay" src="public/play.png" />
</li>
{{else}}
<li data-src="{{urls.large}}"
data-sub-html="{{caption}}"
data-download-url="{{urls.download}}">
<a href="{{urls.download}}">
<img src="{{urls.thumb}}"
width="{{size}}"
height="{{size}}"
alt="{{name}}" />
</a>
</li>
{{/if}}
{{/each}}
</ul>
<div id="videos">
{{#each gallery.media}}
{{#if video}}
<div id="media{{id}}" style="display:none;">
<video class="lg-video-object lg-html5 video-js vjs-default-skin" preload="none" controls>
<source src="{{urls.video}}" type="video/mp4" />
Your browser does not support HTML5 video
</video>
</div>
{{/if}}
{{/each}}
</div>
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<!-- VideoJS -->
<script src="http://vjs.zencdn.net/4.12/video.js"></script>
<!-- LightGallery -->
<script src="public/light-gallery/js/lightgallery.js"></script>
<script src="public/light-gallery/js/lg-autoplay.js"></script>
<script src="public/light-gallery/js/lg-pager.js"></script>
<script src="public/light-gallery/js/lg-thumbnail.js"></script>
<script src="public/light-gallery/js/lg-video.js"></script>
<script>
$(document).ready(function() {
$("#gallery").lightGallery({
thumbWidth: 80,
controls: true,
loop : false,
download: true,
counter: true,
videojs: true
});
});
</script>
{{> analytics}}
</body>
</html>

View File

@ -1,47 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>{{title}} {{subtitle}}</title>
<link rel="stylesheet" href="public/reset.css" />
<link rel="stylesheet" href="public/theme.css" />
{{#if css}}
<link rel="stylesheet" href="public/{{css}}" />
{{/if}}
</head>
<body>
<header>
<h1>{{title}}</h1>
<h2>{{subtitle}}</h2>
</header>
<ul id="galleries">
{{#each galleries}}
<li>
<a href="{{url}}">
<h3>{{name}}</h3>
<div class="meta">
{{stats}}<br />
{{fromDate}} - {{toDate}}
</div>
{{#if grid}}
<ul class="grid">
{{#each grid}}<li><img src="{{this}}" /></li>{{/each}}
</ul>
{{else}}
<img class="single" src="{{single}}" />
{{/if}}
</a>
</li>
{{/each}}
</ul>
{{> analytics}}
</body>
</html>

View File

@ -0,0 +1,12 @@
<!-- This album -->
<a href="{{filename}}.html">
{{#times depth}}-{{/times}}
{{title}}<span class="count">{{stats.total}}</span>
</a>
<!-- And nested album -->
{{#each albums}}
{{> sidebar-album}}
{{/each}}

20
test/file.spec.js Normal file
View File

@ -0,0 +1,20 @@
var should = require('should/as-function');
var File = require('../src/file');
var fixtures = require('./fixtures');
describe('File', function() {
it('stores the file name', function(){
var f = new File('holidays/newyork/IMG_000001.jpg', fixtures.metadata());
should(f.filename).eql('IMG_000001.jpg');
});
it('reads the date from the file <mdate>', function() {
var meta = fixtures.metadata();
meta.fileDate = fixtures.date('2016-09-23');
meta.exif.date = null;
var f = new File('IMG_000001.jpg', meta);
should(f.date).eql(fixtures.date('2016-09-23'));
})
});

45
test/fixtures.js Normal file
View File

@ -0,0 +1,45 @@
var File = require('../src/file');
exports.metadata = function() {
return {
fileDate: new Date(),
mediaType: 'photo',
exif: {
date: null,
orientation: 1,
caption: ''
}
};
};
exports.date = function(str) {
return new Date(Date.parse(str));
};
exports.photo = function(opts) {
opts = opts || {};
var date = opts.date ? new Date(Date.parse(opts.date)) : new Date();
return new File(opts.path || 'tmp', {
fileDate: date,
mediaType: 'photo',
exif: {
date: null,
orientation: 1,
caption: ''
}
});
};
exports.video = function(opts) {
opts = opts || {};
var date = opts.date ? new Date(Date.parse(opts.date)) : new Date();
return new File(opts.path || 'tmp', {
fileDate: date,
mediaType: 'video',
exif: {
date: null,
orientation: 1,
caption: ''
}
});
};

1
test/mocha.opts Normal file
View File

@ -0,0 +1 @@
--recursive

118
test/website/album.spec.js Normal file
View File

@ -0,0 +1,118 @@
var should = require('should/as-function');
var Album = require('../../src/output-website/album');
var fixtures = require('../fixtures');
describe('Album', function() {
it('sanitises album titles for the file name', function() {
var a = new Album('hello & world');
should(a.filename).eql('helloworld');
});
describe('stats', function() {
describe('single level', function() {
it('has no nested albums', function() {
var a = new Album('single');
a.finalize();
should(a.stats.albums).eql(0);
})
it('calculates counts for a single level', function() {
var a = new Album('single');
a.files = [
fixtures.photo(), fixtures.photo(),
fixtures.photo(), fixtures.photo(),
fixtures.video(), fixtures.video(),
];
a.finalize();
should(a.stats.photos).eql(4);
should(a.stats.videos).eql(2);
});
it('calculates dates', function() {
var a = new Album('single');
a.files = [
fixtures.photo({date: '2016-09-14'}),
fixtures.photo({date: '2016-09-02'}),
fixtures.photo({date: '2016-10-21'}),
];
a.finalize();
should(a.stats.fromDate).eql(fixtures.date('2016-09-02'));
should(a.stats.toDate).eql(fixtures.date('2016-10-21'));
});
});
describe('nested albums', function() {
});
describe('summary', function() {
it('creates a summary with a single photos', function() {
var a = new Album('single');
a.files = [
fixtures.photo()
];
a.finalize();
should(a.summary).eql('1 photo')
});
it('creates a summary with a single video', function() {
var a = new Album('single');
a.files = [
fixtures.video()
];
a.finalize();
should(a.summary).eql('1 video')
});
it('creates a summary with several photos', function() {
var a = new Album('single');
a.files = [
fixtures.photo(), fixtures.photo(),
];
a.finalize();
should(a.summary).eql('2 photos')
});
it('creates a summary with several videos', function() {
var a = new Album('single');
a.files = [
fixtures.video(), fixtures.video(),
];
a.finalize();
should(a.summary).eql('2 videos')
});
it('creates a summary with several photos and videos', function() {
var a = new Album('single');
a.files = [
fixtures.photo(), fixtures.photo(),
fixtures.video(), fixtures.video(),
];
a.finalize();
should(a.summary).eql('2 photos, 2 videos')
});
});
describe('previews', function() {
it('adds <missing> thumbnails to fill the 2x2 grid', function() {
var a = new Album({files: [
fixtures.photo(), fixtures.photo(),
]});
a.finalize();
should(a.previews).have.length(4);
should(a.previews[2].urls.thumb).eql('public/missing.png');
should(a.previews[3].urls.thumb).eql('public/missing.png');
});
});
});
});

View File

@ -0,0 +1,44 @@
var should = require('should/as-function');
var Album = require('../../src/output-website/album.js');
var bydate = require('../../src/output-website/by-date.js');
var fixtures = require('../fixtures');
describe('ByDate', function() {
describe('date format', function() {
it('formats a date as YYYY-MM', function() {
should(bydate.format(fixtures.date('2016-06-13T16:43:19'))).eql('2016-06')
});
it('formats based on the local timezone', function() {
// TODO: why doesn't 23:59:59 work? Seems to be converted
should(bydate.format(fixtures.date('1999-01-01T00:00:00'))).eql('1999-01')
should(bydate.format(fixtures.date('1999-12-31T00:00:00'))).eql('1999-12')
});
});
it('creates albums by date', function () {
// create files from different dates
var june1 = fixtures.photo({path: 'some/IMG_000001.jpg', date: fixtures.date('2016-06-01')});
var june2 = fixtures.photo({path: 'folders/IMG_000003.jpg', date: fixtures.date('2016-06-10')});
var july1 = fixtures.photo({path: 'random/IMG_000002.jpg', date: fixtures.date('2016-07-23')});
var july2 = fixtures.video({path: 'and/subfolders/IMG_000004.mp4', date: fixtures.date('2016-07-18')});
// group them per month
var collection = { files: [june1, june2, july1, july2] };
var albums = bydate.albums(collection, {});
// assert on the result
should(albums).eql([
new Album({
'title': '2016-06',
files: [june1, june2]
}),
new Album({
title: '2016-07',
files: [july1, july2]
})
]);
});
});

View File

@ -0,0 +1,30 @@
var should = require('should/as-function');
var Album = require('../../src/output-website/album.js');
var byfolder = require('../../src/output-website/by-folder.js');
var fixtures = require('../fixtures');
describe('ByFolder', function() {
it('creates albums by folders', function () {
// create files in different folders
var london1 = fixtures.photo({path: 'london/IMG_000001.jpg'});
var london2 = fixtures.photo({path: 'london/IMG_000002.jpg'});
var newyork1 = fixtures.photo({path: 'newyork/IMG_000003.jpg'});
var newyork2 = fixtures.video({path: 'newyork/IMG_000004.mp4'});
// group them per folder
var collection = {files: [london1, london2, newyork1, newyork2]};
var albums = byfolder.albums(collection, {});
// assert on the result
should(albums).eql([
new Album({
title: 'london',
files: [london1, london2]
}),
new Album({
title: 'newyork',
files: [newyork1, newyork2]
})
]);
});
});