commit 9a9701467a5187fd3249b879d84793f0c6e5870b Author: Nicolas MASSE Date: Mon Mar 30 16:22:55 2020 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..722d5e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..faff36e --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2020 YOUR_NAME_HERE + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..806704e --- /dev/null +++ b/README.md @@ -0,0 +1,122 @@ +# Photo Stream + +A theme to showcase your photo albums, powered by [Hugo](https://gohugo.io). +A live demo is available [at photo-stream.netlify.com](https://photo-stream.netlify.com/). + +## Features + +This theme is basically a port of [maxvoltar's photo-stream theme](https://github.com/maxvoltar/photo-stream). +Thanks to him for this nice creation! + +This theme features: + +* Lazy loading of photos (a photo is downloaded when it appears in the viewport) +* Albums containing photos +* Photos thumbnail are resized to fit 800x800 +* The large version is resized to fit 2048x2048 +* The background is filled with a tint matching the photo +* Keyboard shortcuts for previous / next / back to list + +## Installation + +You can install the theme either as a clone or submodule. + +I recommend the latter. From the root of your Hugo site, type the following: + +```sh +git submodule add https://github.com/nmasse-itix/photo-stream.git themes/photo-stream +git submodule init +git submodule update +``` + +Now you can get updates of this theme in the future by updating the submodule: + +```sh +git submodule update --remote themes/photo-stream +``` + +## Configuration + +After installation, take a look at the `exampleSite` folder inside `themes/photo-stream`. + +To get started, copy the `config.toml` file inside `exampleSite` to the root of your Hugo site: + +```sh +cp themes/photo-stream/exampleSite/config.toml . +``` + +Now edit this file and add your own information. Note that some fields can be omitted. + +## Demo Website + +A live demo is available [at photo-stream.netlify.com](https://photo-stream.netlify.com/) but you can have a look by yourself at the example site. + +```sh +cd themes/photo-stream +./fetch-photos.sh +hugo serve +``` + +## How to create an album + +The theme provides an **archetype** named `album`. +Create a new album with the `hugo new` command. + +```sh +hugo new my-album/index.md -k album +``` + +## How to add photos + +To add photos to an album, simply copy your JPEG files in the album directory, **under content, NOT static!** + +```sh +cp path/to/DCIM_*.jpeg content/my-album/ +``` + +## How to customize an album + +A minimal `index.md` looks like this: + +```yaml +--- +date: "2016-01-01" +title: Animals +- src: '**.jpeg' +--- +``` + +This index file defines an album with a date, a title and instructs to add all JPEG files to the album. + +But a usual `index.md` would include more customization: + +```yaml +--- +date: "2016-01-01" +title: Animals +sort_by: "Exif.Date" +resources: +- src: 'camel.jpeg' + params: + cover: true +- src: '**.jpeg' +- src: '**.jpg' +--- +``` + +This index also specifies: + +* To sort photos by date (specified in the EXIF metadata). +* To also include files with `.jpg` extension. +* To set `camel.jpeg` as the cover photo for the album. + +## Global configuration + +The Date format for the album can be set in your `config.toml`. + +```toml +[params] +album_date_format = "01/2006" +``` + +Check the Go documentation for possible formats: [time.Format](https://golang.org/pkg/time/#Time.Format). diff --git a/archetypes/album.md b/archetypes/album.md new file mode 100644 index 0000000..229fbb3 --- /dev/null +++ b/archetypes/album.md @@ -0,0 +1,19 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +# By default, photos are sorted by filename +sort_by: Name +# But you can sort instead by EXIF date if you prefer +# sort_by: Exif.Date +resources: +# +# You can set the album cover image by setting the param 'cover: true' +# on a photo. +# +# - src: 'IMG_1234.jpeg' +# params: +# cover: true +# +- src: '**.jpeg' +- src: '**.jpg' +--- diff --git a/assets/css/master.scss b/assets/css/master.scss new file mode 100644 index 0000000..abeda37 --- /dev/null +++ b/assets/css/master.scss @@ -0,0 +1,430 @@ +* { + padding: 0; + margin: 0; + list-style: none; + font-size: 1em; + box-sizing: border-box; +} + +@mixin dark { + @media (prefers-color-scheme: dark) { + @content + } +} + +@mixin button { + display: block; + border-radius: 16px; + text-indent: 150%; + overflow: hidden; + white-space: nowrap; + width: 32px; + height: 32px; + background-repeat: no-repeat; + background-position: 8px; + background-size: 16px; + transition: background-color .1s linear; + -webkit-backdrop-filter: blur(20px); + -moz-backdrop-filter: blur(20px); + backdrop-filter: blur(20px); + background-color: rgba(200, 200, 200, .25); + // Disable until Safari supports `prefers-color-scheme` in SVG's + // @include dark { + // background-color: rgba(0, 0, 0, .25); + // } + + &:hover, + &:focus { + background-color: rgba(200, 200, 200, .5); + // Disable until Safari supports `prefers-color-scheme` in SVG's + // @include dark { + // background-color: rgba(0, 0, 0, .5); + // } + } + + &:active { + background-color: rgba(200, 200, 200, .25); + // Disable until Safari supports `prefers-color-scheme` in SVG's + // @include dark { + // background-color: rgba(0, 0, 0, .75); + // } + } + + +} + +body, +html { + min-height: 100%; + display: flex; +} + +body { + flex-grow: 1; + font: 16px/24px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + background: #fff; + color: #2e2f30; + + @include dark { + background: #000; + color: #eee; + } +} + +// PHOTO GRID + +.grid { + display: flex; + flex-wrap: wrap; + position: relative; + align-content: flex-start; + + &:after { + content: ""; + display: block; + flex-grow: 10; + outline: 2px solid #fff; + position: relative; + + @include dark { + outline-color: #000; + } + } + + .item { + height: 40vh; + flex-grow: 1; + outline: 2px solid #fff; + position: relative; + background-size: 100%; + + @include dark { + outline-color: #000; + } + + img { + max-height: 100%; + min-width: 100%; + min-height: 100%; + width: auto; + object-fit: cover; + display: block; + } + + .open, + .close { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + text-indent: 150%; + overflow: hidden; + white-space: nowrap; + } + + .open { + cursor: zoom-in; + background-color: rgba(0, 0, 0, 0); + transition: background-color .15s ease-out; + + &:hover, + &:focus { + background-color: rgba(0, 0, 0, .25); + } + + &:active { + background-color: rgba(0, 0, 0, .5); + } + } + + .close { + display: none; + cursor: zoom-out; + } + + .full { + display: none; + } + + .previous, + .next { + position: absolute; + top: 0; + bottom: 0; + left: 0; + z-index: 20; + width: 80px; + display: none; + align-items: center; + justify-content: center; + + span { + @include button; + background-image: url(../img/icon-left.svg); + pointer-events: none; + } + + &:hover, + &:focus { + span { + background-color: rgba(200, 200, 200, .5); + // Disable until Safari supports `prefers-color-scheme` in SVG's + // @include dark { + // background-color: rgba(0, 0, 0, .5); + // } + } + } + + &:active { + span { + background-color: rgba(200, 200, 200, .25); + // Disable until Safari supports `prefers-color-scheme` in SVG's + // @include dark { + // background-color: rgba(0, 0, 0, .75); + // } + } + } + } + + .next { + right: 0; + left: auto; + + span { + background-image: url(../img/icon-right.svg); + } + } + + .name { + display: flex; + position: absolute; + right: 4px; + bottom: 12px; + color: #fff; + text-shadow: #000 0 1px 1px, #000 0 2px 4px; + opacity: 1; + font-size: larger; + margin-right: 12px; + } + + .date { + display: flex; + position: absolute; + left: 4px; + bottom: 12px; + color: #fff; + text-shadow: #000 0 1px 1px, #000 0 2px 4px; + opacity: 1; + margin-left: 12px; + } + + // PHOTO DETAIL + + &.target { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + height: 100%; + z-index: 10; + background: #fff; + display: flex; + align-items: center; + + @media (prefers-color-scheme: dark) { + background: #000; + } + + .open { + display: none; + } + + .close { + display: block; + } + + img { + object-fit: contain; + animation: fade-in .5s ease-out; + } + + .full { + display: flex; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + animation: fade-in .5s ease-out; + + span { + flex-grow: 1; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + } + } + + .meta { + display: none !important; + } + + .previous, + .next { + display: flex; + } + } + } +} + +// SOCIAL LINKS + +.links { + position: fixed; + bottom: 24px; + right: 24px; + display: flex; + flex-wrap: wrap; + margin-left: 16px; + + li { + margin-left: 8px; + + a { + @include button; + } + + &.github { + a { + background-image: url(../img/icon-github.svg); + } + } + + &.rss { + a { + background-image: url(../img/icon-rss.svg); + } + } + + &.link { + a { + text-indent: 0; + width: auto; + font-size: 13px; + line-height: 32px; + text-transform: uppercase; + padding: 0 12px; + color: rgba(0, 0, 0, .75); + font-weight: 600; + text-decoration: none; + } + } + } +} + +// 404 + +.four-oh-four { + flex-grow: 1; + display: flex; + flex-direction: column; + height: 100%; + padding: 64px; + align-items: center; + justify-content: center; + text-align: center; + + img { + width: 64px; + vertical-align: bottom; + margin-bottom: 24px; + } + + h1 { + font-size: 32px; + line-height: 48px; + font-weight: 700; + } + + p { + margin-bottom: 32px; + } + + a { + @include button; + text-indent: 0; + width: auto; + font-size: 13px; + line-height: 32px; + text-transform: uppercase; + padding: 0 12px; + color: rgba(0, 0, 0, .75); + font-weight: 600; + text-decoration: none; + } +} + +// RESPONSIVE + +@media (max-aspect-ratio: 1/1) { + .grid { + .item { + height: 30vh; + } + } +} + +@media (max-height: 480px) { + .grid { + .item { + height: 80vh; + } + } +} + +@media (max-aspect-ratio: 1/1) and (max-width: 480px) { + .grid { + flex-direction: row; + + .item { + height: auto; + width: 100%; + + img { + width: 100%; + height: auto; + } + + .previous, + .next { + width: 25vw; + max-width: auto; + + span { + display: none; + } + } + + .previous { + cursor: w-resize; + } + + .next { + cursor: e-resize; + } + } + } +} + +// ANIMATIONS + +@keyframes fade-in { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} \ No newline at end of file diff --git a/exampleSite/.gitignore b/exampleSite/.gitignore new file mode 100644 index 0000000..fc47808 --- /dev/null +++ b/exampleSite/.gitignore @@ -0,0 +1 @@ +resources \ No newline at end of file diff --git a/exampleSite/config.toml b/exampleSite/config.toml new file mode 100644 index 0000000..a864690 --- /dev/null +++ b/exampleSite/config.toml @@ -0,0 +1,4 @@ +title = "Photo Stream" +theme = "photo-stream" +[params] +album_date_format = "2006" diff --git a/exampleSite/content/.gitignore b/exampleSite/content/.gitignore new file mode 100644 index 0000000..da9b1d2 --- /dev/null +++ b/exampleSite/content/.gitignore @@ -0,0 +1 @@ +*.jpeg \ No newline at end of file diff --git a/exampleSite/content/animals/index.md b/exampleSite/content/animals/index.md new file mode 100644 index 0000000..e4b2e55 --- /dev/null +++ b/exampleSite/content/animals/index.md @@ -0,0 +1,10 @@ +--- +date: "2016-01-01" +title: Animals +sort_by: "Name" +resources: +- src: 'camel.jpeg' + params: + cover: true +- src: '**.jpeg' +--- diff --git a/exampleSite/content/architecture/index.md b/exampleSite/content/architecture/index.md new file mode 100644 index 0000000..fe9d70b --- /dev/null +++ b/exampleSite/content/architecture/index.md @@ -0,0 +1,10 @@ +--- +date: "2020-01-01" +title: Architecture +sort_by: "Name" +resources: +- src: 'archi10.jpeg' + params: + cover: true +- src: '**.jpeg' +--- diff --git a/exampleSite/content/empty/index.md b/exampleSite/content/empty/index.md new file mode 100644 index 0000000..5293b7e --- /dev/null +++ b/exampleSite/content/empty/index.md @@ -0,0 +1,7 @@ +--- +date: "2020-01-01" +title: Architecture +sort_by: "Exif.Date" +resources: +- src: '**.jpeg' +--- diff --git a/exampleSite/content/flowers/index.md b/exampleSite/content/flowers/index.md new file mode 100644 index 0000000..fd972d8 --- /dev/null +++ b/exampleSite/content/flowers/index.md @@ -0,0 +1,10 @@ +--- +date: "2019-01-01" +title: Flowers +sort_by: "Name" +resources: +- src: 'flower09.jpeg' + params: + cover: true +- src: '**.jpeg' +--- diff --git a/exampleSite/content/food/index.md b/exampleSite/content/food/index.md new file mode 100644 index 0000000..e215194 --- /dev/null +++ b/exampleSite/content/food/index.md @@ -0,0 +1,10 @@ +--- +date: "2017-01-01" +title: Food and drink +sort_by: "Name" +resources: +- src: 'food06.jpeg' + params: + cover: true +- src: '**.jpeg' +--- diff --git a/exampleSite/content/happy/index.md b/exampleSite/content/happy/index.md new file mode 100644 index 0000000..f868e49 --- /dev/null +++ b/exampleSite/content/happy/index.md @@ -0,0 +1,7 @@ +--- +date: "2015-01-01" +title: Happy +sort_by: "Name" +resources: +- src: '**.jpeg' +--- diff --git a/exampleSite/content/love/index.md b/exampleSite/content/love/index.md new file mode 100644 index 0000000..de7dcac --- /dev/null +++ b/exampleSite/content/love/index.md @@ -0,0 +1,10 @@ +--- +date: "2014-01-01" +title: Love +sort_by: "Name" +resources: +- src: 'love02.jpeg' + params: + cover: true +- src: '**.jpeg' +--- diff --git a/exampleSite/content/people/index.md b/exampleSite/content/people/index.md new file mode 100644 index 0000000..a21fae9 --- /dev/null +++ b/exampleSite/content/people/index.md @@ -0,0 +1,7 @@ +--- +date: "2013-01-01" +title: People +sort_by: "Name" +resources: +- src: '**.jpeg' +--- diff --git a/exampleSite/content/tints/index.md b/exampleSite/content/tints/index.md new file mode 100644 index 0000000..9bfb505 --- /dev/null +++ b/exampleSite/content/tints/index.md @@ -0,0 +1,7 @@ +--- +date: "2012-01-01" +title: Tints +sort_by: "Name" +resources: +- src: '**.jpeg' +--- diff --git a/exampleSite/content/travel/index.md b/exampleSite/content/travel/index.md new file mode 100644 index 0000000..814b8e9 --- /dev/null +++ b/exampleSite/content/travel/index.md @@ -0,0 +1,7 @@ +--- +date: "2011-01-01" +title: Travel +sort_by: "Name" +resources: +- src: '**.jpeg' +--- diff --git a/exampleSite/fetch-photos.sh b/exampleSite/fetch-photos.sh new file mode 100755 index 0000000..ed6ab80 --- /dev/null +++ b/exampleSite/fetch-photos.sh @@ -0,0 +1,130 @@ +#!/bin/bash + +function fetch() { + file=$1 + url=$2 + if [ ! -e "$1" ]; then + echo "Fetching $1... " + curl -sL -o "$1" "$2" + if [ "$?" -gt 0 ]; then + echo "Failed !" + fi + else + echo "Skipping $1, the file already exists!" + fi +} + +fetch "content/animals/hawk.jpeg" "https://unsplash.com/photos/H27PUqaJyHU/download?force=true" +fetch "content/animals/dog.jpeg" "https://unsplash.com/photos/Am3RoG7GEl0/download?force=true" +fetch "content/animals/cat.jpeg" "https://unsplash.com/photos/G21-GaAZrrs/download?force=true" +fetch "content/animals/bee.jpeg" "https://unsplash.com/photos/VeRn-bKfoVA/download?force=true" +fetch "content/animals/monkey.jpeg" "https://unsplash.com/photos/4nPq-CMKfvY/download?force=true" +fetch "content/animals/turtle.jpeg" "https://unsplash.com/photos/_x-PryfGq0Y/download?force=true" +fetch "content/animals/horse.jpeg" "https://unsplash.com/photos/dr1Hbu8Gwt8/download?force=true" +fetch "content/animals/bird.jpeg" "https://unsplash.com/photos/YezZZpufVL4/download?force=true" +fetch "content/animals/bird2.jpeg" "https://unsplash.com/photos/ZbMJ5VLrpQ4/download?force=true" +fetch "content/animals/spider.jpeg" "https://unsplash.com/photos/BkV2pxgof-U/download?force=true" +fetch "content/animals/wolf.jpeg" "https://unsplash.com/photos/9rloii_qmmw/download?force=true" +fetch "content/animals/dog2.jpeg" "https://unsplash.com/photos/Oq9NDnlFQzU/download?force=true" +fetch "content/animals/fox.jpeg" "https://unsplash.com/photos/oCxaclJklOI/download?force=true" +fetch "content/animals/dog3.jpeg" "https://unsplash.com/photos/8o5uCdOQtko/download?force=true" +fetch "content/animals/camel.jpeg" "https://unsplash.com/photos/i_Z1o10BPPk/download?force=true" +fetch "content/animals/bee2.jpeg" "https://unsplash.com/photos/UPJ0vTjPFXE/download?force=true" +fetch "content/animals/wasp.jpeg" "https://unsplash.com/photos/R_W86FHa-Sk/download?force=true" +fetch "content/animals/dog4.jpeg" "https://unsplash.com/photos/Ugg-EIfzy0c/download?force=true" +fetch "content/animals/rabbit.jpeg" "https://unsplash.com/photos/8bOwZ8ag9UY/download?force=true" +fetch "content/animals/fish.jpeg" "https://unsplash.com/photos/l-QdJMZX7PU/download?force=true" + +fetch "content/architecture/archi01.jpeg" "https://unsplash.com/photos/37Hk9D4Ig_4/download?force=true" +fetch "content/architecture/archi02.jpeg" "https://unsplash.com/photos/3pk1VnBeTQQ/download?force=true" +fetch "content/architecture/archi03.jpeg" "https://unsplash.com/photos/t1tAOh-CaZ4/download?force=true" +fetch "content/architecture/archi04.jpeg" "https://unsplash.com/photos/w6OniVDCfn0/download?force=true" +fetch "content/architecture/archi05.jpeg" "https://unsplash.com/photos/zZ97YKTyj7s/download?force=true" +fetch "content/architecture/archi06.jpeg" "https://unsplash.com/photos/tNGfc-2KNrc/download?force=true" +fetch "content/architecture/archi07.jpeg" "https://unsplash.com/photos/LmS1g1fqyas/download?force=true" +fetch "content/architecture/archi08.jpeg" "https://unsplash.com/photos/I-LFXWk3vLI/download?force=true" +fetch "content/architecture/archi09.jpeg" "https://unsplash.com/photos/4VBFrMweUw8/download?force=true" +fetch "content/architecture/archi10.jpeg" "https://unsplash.com/photos/lLs02_axGOw/download?force=true" +fetch "content/architecture/archi11.jpeg" "https://unsplash.com/photos/NJ3JeCFwj9g/download?force=true" +fetch "content/architecture/archi12.jpeg" "https://unsplash.com/photos/R63O6UiUEzg/download?force=true" +fetch "content/architecture/archi13.jpeg" "https://unsplash.com/photos/IU1QUXkD-90/download?force=true" +fetch "content/architecture/archi14.jpeg" "https://unsplash.com/photos/8o_x-NjXIcQ/download?force=true" +fetch "content/architecture/archi15.jpeg" "https://unsplash.com/photos/YKAUA_Rt6xI/download?force=true" +fetch "content/architecture/archi16.jpeg" "https://unsplash.com/photos/zUOqjnO_ZvM/download?force=true" +fetch "content/architecture/archi17.jpeg" "https://unsplash.com/photos/s07In41ntgg/download?force=true" +fetch "content/architecture/archi18.jpeg" "https://unsplash.com/photos/QsDEa0qvk20/download?force=true" +fetch "content/architecture/archi19.jpeg" "https://unsplash.com/photos/cxyPcOcClSE/download?force=true" +fetch "content/architecture/archi20.jpeg" "https://unsplash.com/photos/fwsiAb2LLZE/download?force=true" + +fetch "content/flowers/flower01.jpeg" "https://unsplash.com/photos/EfhCUc_fjrU/download?force=true" +fetch "content/flowers/flower02.jpeg" "https://unsplash.com/photos/9A_peGrSbZc/download?force=true" +fetch "content/flowers/flower03.jpeg" "https://unsplash.com/photos/tu_mv6p2p5U/download?force=true" +fetch "content/flowers/flower04.jpeg" "https://unsplash.com/photos/koy6FlCCy5s/download?force=true" +fetch "content/flowers/flower05.jpeg" "https://unsplash.com/photos/ct_zXHu8rcM/download?force=true" +fetch "content/flowers/flower06.jpeg" "https://unsplash.com/photos/5lRxNLHfZOY/download?force=true" +fetch "content/flowers/flower07.jpeg" "https://unsplash.com/photos/iMdsjoiftZo/download?force=true" +fetch "content/flowers/flower08.jpeg" "https://unsplash.com/photos/OWq8w3BYMFY/download?force=true" +fetch "content/flowers/flower09.jpeg" "https://unsplash.com/photos/ATgfRqpFfFI/download?force=true" +fetch "content/flowers/flower10.jpeg" "https://unsplash.com/photos/YmPqWIQcl9c/download?force=true" +fetch "content/flowers/flower11.jpeg" "https://unsplash.com/photos/urUdKCxsTUI/download?force=true" +fetch "content/flowers/flower12.jpeg" "https://unsplash.com/photos/p7mo8-CG5Gs/download?force=true" +fetch "content/flowers/flower13.jpeg" "https://unsplash.com/photos/f0heeiu-Ec0/download?force=true" +fetch "content/flowers/flower14.jpeg" "https://unsplash.com/photos/IicyiaPYGGI/download?force=true" +fetch "content/flowers/flower15.jpeg" "https://unsplash.com/photos/KQ6sO8m1ZDE/download?force=true" +fetch "content/flowers/flower16.jpeg" "https://unsplash.com/photos/kkJuQhp9Kw0/download?force=true" +fetch "content/flowers/flower17.jpeg" "https://unsplash.com/photos/aolmXcUxr7Y/download?force=true" +fetch "content/flowers/flower18.jpeg" "https://unsplash.com/photos/zb2vBaHYB2I/download?force=true" +fetch "content/flowers/flower19.jpeg" "https://unsplash.com/photos/BlMj6RYy3c0/download?force=true" +fetch "content/flowers/flower20.jpeg" "https://unsplash.com/photos/whOkVvf0_hU/download?force=true" + +fetch "content/food/food01.jpeg" "https://unsplash.com/photos/oyr21Ey_DPI/download?force=true" +fetch "content/food/food02.jpeg" "https://unsplash.com/photos/8CSYziKPFV4/download?force=true" +fetch "content/food/food03.jpeg" "https://unsplash.com/photos/8W1KIj8iWX4/download?force=true" +fetch "content/food/food04.jpeg" "https://unsplash.com/photos/D7NA2pEn3K0/download?force=true" +fetch "content/food/food05.jpeg" "https://unsplash.com/photos/IlnF2g_3tpY/download?force=true" +fetch "content/food/food06.jpeg" "https://unsplash.com/photos/qNhe2QXzLuo/download?force=true" +fetch "content/food/food07.jpeg" "https://unsplash.com/photos/1J1mEZbag4I/download?force=true" +fetch "content/food/food08.jpeg" "https://unsplash.com/photos/phEaeqe555M/download?force=true" +fetch "content/food/food09.jpeg" "https://unsplash.com/photos/G3GxkxZOOYc/download?force=true" +fetch "content/food/food10.jpeg" "https://unsplash.com/photos/dmnCGaqMEzE/download?force=true" +fetch "content/food/food11.jpeg" "https://unsplash.com/photos/TAj4X5-eRqE/download?force=true" +fetch "content/food/food12.jpeg" "https://unsplash.com/photos/H0fOnITjgw8/download?force=true" +fetch "content/food/food13.jpeg" "https://unsplash.com/photos/MqT0asuoIcU/download?force=true" +fetch "content/food/food14.jpeg" "https://unsplash.com/photos/EGvhPABaBos/download?force=true" +fetch "content/food/food15.jpeg" "https://unsplash.com/photos/_MYcIi9DgYQ/download?force=true" +fetch "content/food/food16.jpeg" "https://unsplash.com/photos/KG8ofkGRl1k/download?force=true" +fetch "content/food/food17.jpeg" "https://unsplash.com/photos/C6JhUKs9q8M/download?force=true" +fetch "content/food/food18.jpeg" "https://unsplash.com/photos/JyxMyWKOlSU/download?force=true" +fetch "content/food/food19.jpeg" "https://unsplash.com/photos/ta6KsvFaBqk/download?force=true" +fetch "content/food/food20.jpeg" "https://unsplash.com/photos/aZfMW0hSnQI/download?force=true" + +fetch "content/happy/happy01.jpeg" "https://unsplash.com/photos/TyQ-0lPp6e4/download?force=true" +fetch "content/happy/happy02.jpeg" "https://unsplash.com/photos/e3OUQGT9bWU/download?force=true" +fetch "content/happy/happy03.jpeg" "https://unsplash.com/photos/FtZL0r4DZYk/download?force=true" +fetch "content/happy/happy04.jpeg" "https://unsplash.com/photos/hRdVSYpffas/download?force=true" +fetch "content/happy/happy05.jpeg" "https://unsplash.com/photos/1AhGNGKuhR0/download?force=true" + + +fetch "content/love/love01.jpeg" "https://unsplash.com/photos/YRgPxwbvY0E/download?force=true" +fetch "content/love/love02.jpeg" "https://unsplash.com/photos/AsahNlC0VhQ/download?force=true" +fetch "content/love/love03.jpeg" "https://unsplash.com/photos/EdULZpOKsUE/download?force=true" +fetch "content/love/love04.jpeg" "https://unsplash.com/photos/Y9mWkERHYCU/download?force=true" +fetch "content/love/love05.jpeg" "https://unsplash.com/photos/bQxGg8Vx1Vc/download?force=true" + +fetch "content/people/people01.jpeg" "https://unsplash.com/photos/4nulm-JUYFo/download?force=true" +fetch "content/people/people02.jpeg" "https://unsplash.com/photos/NAdFJtFFlHE/download?force=true" +fetch "content/people/people03.jpeg" "https://unsplash.com/photos/2RhlxwRz4yc/download?force=true" +fetch "content/people/people04.jpeg" "https://unsplash.com/photos/tokYjYqaPB0/download?force=true" +fetch "content/people/people05.jpeg" "https://unsplash.com/photos/by0XNgDemsc/download?force=true" + +fetch "content/tints/tint01.jpeg" "https://unsplash.com/photos/kKvQJ6rK6S4/download?force=true" +fetch "content/tints/tint02.jpeg" "https://unsplash.com/photos/Lw7BruqPnJY/download?force=true" +fetch "content/tints/tint03.jpeg" "https://unsplash.com/photos/60eMQfQuGIk/download?force=true" +fetch "content/tints/tint04.jpeg" "https://unsplash.com/photos/Q4q7kJxqfGI/download?force=true" +fetch "content/tints/tint05.jpeg" "https://unsplash.com/photos/PsO_PfLXET4/download?force=true" + +fetch "content/travel/travel01.jpeg" "https://unsplash.com/photos/Q2ET6TX1poU/download?force=true" +fetch "content/travel/travel02.jpeg" "https://unsplash.com/photos/c5F1hhK5t0Q/download?force=true" +fetch "content/travel/travel03.jpeg" "https://unsplash.com/photos/A7KD1kdXD-o/download?force=true" +fetch "content/travel/travel04.jpeg" "https://unsplash.com/photos/PSY_KuMcTJU/download?force=true" +fetch "content/travel/travel05.jpeg" "https://unsplash.com/photos/rlIb6DLWcH8/download?force=true" diff --git a/exampleSite/themes/photo-stream b/exampleSite/themes/photo-stream new file mode 120000 index 0000000..6581736 --- /dev/null +++ b/exampleSite/themes/photo-stream @@ -0,0 +1 @@ +../../ \ No newline at end of file diff --git a/i18n/en.yaml b/i18n/en.yaml new file mode 100644 index 0000000..490e696 --- /dev/null +++ b/i18n/en.yaml @@ -0,0 +1,11 @@ +--- +- id: pageNotFound + translation: "Sorry, this page does not exist." +- id: visitHomePage + translation: "Return to home page" +- id: open + translation: "Open" +- id: previous + translation: "Previous" +- id: next + translation: "Next" \ No newline at end of file diff --git a/i18n/fr.yaml b/i18n/fr.yaml new file mode 100644 index 0000000..00d9e04 --- /dev/null +++ b/i18n/fr.yaml @@ -0,0 +1,10 @@ +- id: pageNotFound + translation: "Désolé, cette page n'existe pas !" +- id: visitHomePage + translation: "Retour à la page d'accueil" +- id: open + translation: "Ouvrir" +- id: previous + translation: "Précédent" +- id: next + translation: "Suivant" diff --git a/layouts/404.html b/layouts/404.html new file mode 100644 index 0000000..235dfe6 --- /dev/null +++ b/layouts/404.html @@ -0,0 +1,8 @@ +{{ define "main"}} +
+ +

404

+

{{ i18n "pageNotFound" }}

+ {{ i18n "visitHomePage" }} +
+{{ end }} diff --git a/layouts/_default/album.html b/layouts/_default/album.html new file mode 100644 index 0000000..766b9ce --- /dev/null +++ b/layouts/_default/album.html @@ -0,0 +1,33 @@ +{{ $photos := .Resources.ByType "image" }} +{{ $scratch := newScratch }} +{{ $scratch.Set "index" 0 }} +{{ range $i, $photo := $photos }} + {{ if index $photo.Params "cover" }} + {{ $scratch.Set "index" $i }} + {{ end }} +{{ end }} +{{ if gt (len $photos) 0 }} + {{ $photo := index $photos ($scratch.Get "index") }} + {{ if $photo.Exif }} + {{ $orientation := index $photo.Exif.Tags "Orientation" }} + {{ if eq $orientation 6 }} + {{ $scratch.Set "image_rotation" "r270" }} + {{ else if eq $orientation 8 }} + {{ $scratch.Set "image_rotation" "r90" }} + {{ else if eq $orientation 3 }} + {{ $scratch.Set "image_rotation" "r180" }} + {{ else }} + {{ $scratch.Set "image_rotation" "" }} + {{ end }} + {{ else }} + {{ $scratch.Set "image_rotation" "" }} + {{ end }} + {{ $tint := $photo.Fill "1x1 Box png" }} + {{ $thumbnail := $photo.Fit (print "800x800 Lanczos q80 " ($scratch.Get "image_rotation")) }} +
  • + + {{ i18n "open" }} +
    {{ .Title }}
    +
    {{ dateFormat ((index .Site.Params "album_date_format") | default "01/2006") .Date }}
    +
  • +{{ end }} \ No newline at end of file diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html new file mode 100644 index 0000000..4972839 --- /dev/null +++ b/layouts/_default/baseof.html @@ -0,0 +1,7 @@ + + + {{- partial "head.html" . -}} + + {{- block "main" . }}{{- end }} + + diff --git a/layouts/_default/list.html b/layouts/_default/list.html new file mode 100644 index 0000000..c562eb8 --- /dev/null +++ b/layouts/_default/list.html @@ -0,0 +1,8 @@ + +{{ define "main"}} + +{{ end }} diff --git a/layouts/_default/single.html b/layouts/_default/single.html new file mode 100644 index 0000000..b828b86 --- /dev/null +++ b/layouts/_default/single.html @@ -0,0 +1,6 @@ +{{ define "main"}} + +{{ end }} \ No newline at end of file diff --git a/layouts/partials/head.html b/layouts/partials/head.html new file mode 100644 index 0000000..0fb7ae3 --- /dev/null +++ b/layouts/partials/head.html @@ -0,0 +1,55 @@ + + + {{ $url := replace .Permalink ( printf "%s" .Site.BaseURL) "" }} + {{ if eq $url "/" }} + {{ $.Scratch.Set "title" .Site.Title }} + {{ else }} + {{ $.Scratch.Set "title" .Title }} + {{ end }} + + + {{ $.Scratch.Get "title" }} + + + + + + + + + {{ range .AlternativeOutputFormats -}} + {{ printf `` .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }} + {{ end -}} + + + {{ template "_internal/opengraph.html" . }} + + + {{ $scss := resources.Get "/css/master.scss" }} + {{ $css := $scss | resources.ToCSS }} + + + {{ if .Site.Params.cachebuster }} + {{ $t := now }} + + {{ range .Site.Params.extracssfiles }} + + {{ end }} + + + {{ else }} + + {{ range .Site.Params.extracssfiles }} + + {{ end }} + + + {{ end }} + + + + + + + diff --git a/layouts/partials/links.html b/layouts/partials/links.html new file mode 100644 index 0000000..82dd811 --- /dev/null +++ b/layouts/partials/links.html @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/layouts/partials/photos.html b/layouts/partials/photos.html new file mode 100644 index 0000000..43d1eba --- /dev/null +++ b/layouts/partials/photos.html @@ -0,0 +1,45 @@ +{{ $photos := . }} +{{ $size := len $photos }} +{{ $scratch := newScratch }} +{{ range $index, $photo := $photos }} + {{ if $photo.Exif }} + {{ $orientation := index $photo.Exif.Tags "Orientation" }} + {{ if eq $orientation 6 }} + {{ $scratch.Set "image_rotation" "r270" }} + {{ else if eq $orientation 8 }} + {{ $scratch.Set "image_rotation" "r90" }} + {{ else if eq $orientation 3 }} + {{ $scratch.Set "image_rotation" "r180" }} + {{ else }} + {{ $scratch.Set "image_rotation" "" }} + {{ end }} + {{ else }} + {{ $scratch.Set "image_rotation" "" }} + {{ end }} + {{ $tint := $photo.Fill "1x1 Box png" }} + {{ $thumbnail := $photo.Fit (print "800x800 Lanczos q80 " ($scratch.Get "image_rotation")) }} + {{ $large := $photo.Fit (print "2048x2048 Lanczos q85 " ($scratch.Get "image_rotation")) }} +
  • + + + + + + {{ i18n "open" }} + Close + + {{ if $index }} + {{ $previous_photo := (index $photos (sub $index 1)) }} + + {{ end }} + + {{ if lt $index (sub $size 1) }} + {{ $next_photo := (index $photos (add $index 1)) }} + + {{ end }} +
  • +{{ end }} \ No newline at end of file diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000..0a36962 Binary files /dev/null and b/static/favicon.png differ diff --git a/static/favicon.svg b/static/favicon.svg new file mode 100644 index 0000000..f483d15 --- /dev/null +++ b/static/favicon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/static/img/icon-github.svg b/static/img/icon-github.svg new file mode 100644 index 0000000..5d36b53 --- /dev/null +++ b/static/img/icon-github.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/static/img/icon-info.svg b/static/img/icon-info.svg new file mode 100644 index 0000000..b27e8dd --- /dev/null +++ b/static/img/icon-info.svg @@ -0,0 +1,11 @@ + + + + icon-info + Created with Sketch Beta. + + + + + + \ No newline at end of file diff --git a/static/img/icon-left.svg b/static/img/icon-left.svg new file mode 100644 index 0000000..b79dba6 --- /dev/null +++ b/static/img/icon-left.svg @@ -0,0 +1,14 @@ + + + + icon-left + Created with Sketch Beta. + + + + + + + diff --git a/static/img/icon-right.svg b/static/img/icon-right.svg new file mode 100644 index 0000000..1565234 --- /dev/null +++ b/static/img/icon-right.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/static/img/icon-rss.svg b/static/img/icon-rss.svg new file mode 100644 index 0000000..761cf50 --- /dev/null +++ b/static/img/icon-rss.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/static/img/icon-twitter.svg b/static/img/icon-twitter.svg new file mode 100644 index 0000000..3b65026 --- /dev/null +++ b/static/img/icon-twitter.svg @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/static/js/lazy-loading.js b/static/js/lazy-loading.js new file mode 100644 index 0000000..f152038 --- /dev/null +++ b/static/js/lazy-loading.js @@ -0,0 +1,6 @@ +// Name: Lazy Load 2.0.0-rc.2 +// Source: https://github.com/tuupola/lazyload +// License: MIT license +// Copyright: 2007-2019 Mika Tuupola + +!function(t,e){"object"==typeof exports?module.exports=e(t):"function"==typeof define&&define.amd?define([],e):t.LazyLoad=e(t)}("undefined"!=typeof global?global:this.window||this.global,function(t){"use strict";function e(t,e){this.settings=s(r,e||{}),this.images=t||document.querySelectorAll(this.settings.selector),this.observer=null,this.init()}"function"==typeof define&&define.amd&&(t=window);const r={src:"data-src",srcset:"data-srcset",selector:".lazyload",root:null,rootMargin:"0px",threshold:0},s=function(){let t={},e=!1,r=0,o=arguments.length;"[object Boolean]"===Object.prototype.toString.call(arguments[0])&&(e=arguments[0],r++);for(;r { + const id = window.history.state && window.history.state.id; + if (id) { + const photo = document.getElementById(id); + console.log(photo); + const button = photo.querySelector(buttonClass); + console.log(button); + button && button.click(); + } +} + +const openPhoto = (id, href) => { + console.log(`Opening photo ${id}...`); + const photo = document.getElementById(id); + const title = photo.getAttribute('title'); + removeTargetClass(); + photo.classList.add(TARGET_CLASS); + document.title = title; + if (href) { + window.history.pushState({id: id}, '', href); + } +} + +const closePhoto = (href) => { + console.log(`Closing photo...`); + const title = document.querySelector('head title').getAttribute('data-title'); + removeTargetClass(); + document.title = title; + if (href) { + window.history.pushState({}, '', href); + } +} + +const removeTargetClass = () => { + let targets = document.querySelectorAll(`.${TARGET_CLASS}`); + targets.forEach((target) => { + target.classList.remove(TARGET_CLASS); + }); +} + +const handleClick = (selector, event, callback) => { + if (event.target.matches(selector)) { + callback(); + event.preventDefault(); + } +} + +const handleKey = (keyCode, event, callback) => { + if (event.keyCode === keyCode) { + callback(); + event.preventDefault(); + } +} + +window.onpopstate = function(event) { + if (event.state && event.state.id) { + const id = event.state.id; + openPhoto(id, null); + } else { + closePhoto(null); + } +} + +document.addEventListener('keydown', (event) => { + handleKey(ESCAPE, event, () => { + clickNavigationButton('.close'); + }); + + handleKey(RIGHT, event, () => { + clickNavigationButton('.next'); + }); + + handleKey(LEFT, event, () => { + clickNavigationButton('.previous'); + }); +}); + +document.addEventListener('click', (event) => { + handleClick('[data-target][href]', event, () => { + const id = event.target.getAttribute('data-target'); + const href = event.target.getAttribute('href'); + openPhoto(id, href); + }); + + handleClick('[href].close', event, () => { + const href = event.target.getAttribute('href'); + closePhoto(href); + }); +}); + +window.addEventListener('load', (event) => { + console.log("Loaded !"); + const id = window.location.hash.substr(1); + if (id != "") { + openPhoto(id, "#" + id); + } + lazyload(); +}); + diff --git a/static/social-preview.png b/static/social-preview.png new file mode 100644 index 0000000..db9e073 Binary files /dev/null and b/static/social-preview.png differ diff --git a/static/touch-icon-iphone.png b/static/touch-icon-iphone.png new file mode 100644 index 0000000..2e86f27 Binary files /dev/null and b/static/touch-icon-iphone.png differ diff --git a/theme.toml b/theme.toml new file mode 100644 index 0000000..e14f005 --- /dev/null +++ b/theme.toml @@ -0,0 +1,20 @@ +# theme.toml template for a Hugo theme +# See https://github.com/gohugoio/hugoThemes#themetoml for an example + +name = "Photo Stream" +license = "MIT" +licenselink = "https://github.com/nmasse-itix/photo-stream/blob/master/LICENSE" +description = "A theme to host your photo albums, based on maxvoltar's photo-stream theme" +homepage = "https://www.itix.fr/" +tags = [ "photo-stream", "responsive", "flexbox", "minimalistic", "gallery" ] +features = [ "rss", "page resources", "responsive" ] +min_version = "0.68.0" + +[author] + name = "Nicolas Massé" + homepage = "https://www.itix.fr/" + +[original] + name = "Tim Van Damme" + homepage = "http://timvandamme.com/" + repo = "https://github.com/maxvoltar/photo-stream"