From 59b9bdbbd2988b2db348ab253d9bfabfa2f3a594 Mon Sep 17 00:00:00 2001 From: Romain Date: Mon, 6 Mar 2017 23:46:46 +1100 Subject: [PATCH] Use for code style, which removed lots of unused variables/requires --- README.md | 1 + bin/thumbsup.js | 49 ++-- package.json | 15 +- scripts/cibuild | 3 + src/index.js | 4 - src/input/database.js | 5 +- src/input/output.js | 9 +- src/model/album.js | 176 +++++++-------- src/model/by-date.js | 46 ++-- src/model/by-folder.js | 42 ++-- src/model/hierarchy.js | 8 +- src/model/media.js | 2 +- src/output-media/resize.js | 12 +- src/output-website/template.js | 149 ++++++------- src/output-website/website.js | 107 +++++---- src/utils/progress.js | 21 +- test/fixtures.js | 1 - test/input/file.spec.js | 4 +- test/model/album-stats.spec.js | 194 ++++++++-------- test/model/album.spec.js | 395 ++++++++++++++++----------------- test/model/by-date.spec.js | 48 ++-- test/model/by-folder.spec.js | 44 ++-- test/model/media.spec.js | 18 +- 23 files changed, 661 insertions(+), 692 deletions(-) diff --git a/README.md b/README.md index cddb61c..12c5893 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![Travis CI](https://travis-ci.org/thumbsup/node-thumbsup.svg?branch=master)](https://travis-ci.org/thumbsup/node-thumbsup) [![Dependencies](http://img.shields.io/david/thumbsup/node-thumbsup.svg?style=flat)](https://david-dm.org/thumbsup/node-thumbsup) [![Dev dependencies](https://david-dm.org/thumbsup/node-thumbsup/dev-status.svg?style=flat)](https://david-dm.org/thumbsup/node-thumbsup?type=dev) +[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](http://standardjs.com/) ![banner](banner.jpg) diff --git a/bin/thumbsup.js b/bin/thumbsup.js index 2fe0a4f..b8c0c2f 100755 --- a/bin/thumbsup.js +++ b/bin/thumbsup.js @@ -1,10 +1,10 @@ #!/usr/bin/env node -var yargs = require('yargs'); -var path = require('path'); -var index = require('../src/index'); +var yargs = require('yargs') +var path = require('path') +var index = require('../src/index') -console.log(''); +console.log('') var opts = yargs .usage('Usages:\n' + ' thumbsup [required] [options]\n' + @@ -126,31 +126,30 @@ var opts = yargs .epilogue('The optional JSON config should contain a single object with one key ' + 'per argument, not including the leading "--". For example:\n\n' + '{ "sort-albums-by": "start-date" }') - .argv; - + .argv // Compatibility -if (opts['sort-folders'] == 'name') opts['sort-albums-by'] = 'title'; -if (opts['sort-folders'] == 'date') opts['sort-albums-by'] = 'start-date'; +if (opts['sort-folders'] === 'name') opts['sort-albums-by'] = 'title' +if (opts['sort-folders'] === 'date') opts['sort-albums-by'] = 'start-date' index.build({ - input: path.resolve(opts['input']), - output: path.resolve(opts['output']), - title: opts['title'], - thumbSize: opts['thumb-size'], - largeSize: opts['large-size'], - originalPhotos: opts['original-photos'], - originalVideos: opts['original-videos'], - albumsFrom: opts['albums-from'], - albumsDateFormat: opts['albums-date-format'], - sortAlbumsBy: opts['sort-albums-by'], + input: path.resolve(opts['input']), + output: path.resolve(opts['output']), + title: opts['title'], + thumbSize: opts['thumb-size'], + largeSize: opts['large-size'], + originalPhotos: opts['original-photos'], + originalVideos: opts['original-videos'], + albumsFrom: opts['albums-from'], + albumsDateFormat: opts['albums-date-format'], + sortAlbumsBy: opts['sort-albums-by'], sortAlbumsDirection: opts['sort-albums-direction'], - sortMediaBy: opts['sort-media-by'], + sortMediaBy: opts['sort-media-by'], sortMediaDirection: opts['sort-media-direction'], - theme: opts['theme'], - css: opts['css'], - googleAnalytics: opts['google-analytics'], - index: opts['index'], - footer: opts['footer'], + theme: opts['theme'], + css: opts['css'], + googleAnalytics: opts['google-analytics'], + index: opts['index'], + footer: opts['footer'], albumsOutputFolder: opts['albums-output-folder'] -}); +}) diff --git a/package.json b/package.json index 4adf442..18609de 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,19 @@ "markdown-toc": "^0.13.0", "mocha": "^3.1.2", "require-lint": "^1.1.2", - "should": "^11.1.1" + "should": "^11.1.1", + "standard": "^9.0.0" + }, + "standard": { + "ignore": [ + "public/**" + ], + "globals": [ + "afterEach", + "beforeEach", + "describe", + "it", + "xit" + ] } } diff --git a/scripts/cibuild b/scripts/cibuild index 4c2dd0c..47e25c1 100755 --- a/scripts/cibuild +++ b/scripts/cibuild @@ -9,6 +9,9 @@ PATH=$(pwd)/node_modules/.bin:$PATH echo "--- Check all dependencies in package.json" require-lint --src bin/thumbsup.js --ignore-extra lightgallery +echo "--- Static code analysis" +standard + echo "--- Verify lightgallery dependency is built in" grep \"lightgallery\" package.json 1>/dev/null diff --git a/src/index.js b/src/index.js index 1e845e8..85dc2c0 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,5 @@ const async = require('async') const fs = require('fs-extra') -const pad = require('pad') const path = require('path') const database = require('./input/database') const progress = require('./utils/progress') @@ -11,12 +10,10 @@ const resize = require('./output-media/resize') const website = require('./output-website/website') exports.build = function (opts) { - resize.sizes.thumb = opts.thumbSize resize.sizes.large = opts.largeSize fs.mkdirpSync(opts.output) - const media = path.join(opts.output, 'media') const databaseFile = path.join(opts.output, 'metadata.json') var album = null // root album with nested albums @@ -62,7 +59,6 @@ exports.build = function (opts) { } ], finish) - } function asyncProgress (bar) { diff --git a/src/input/database.js b/src/input/database.js index dd36a50..401f3ff 100644 --- a/src/input/database.js +++ b/src/input/database.js @@ -1,10 +1,8 @@ const debug = require('debug')('thumbsup') const exifdb = require('exiftool-json-db') -const pad = require('pad') const progress = require('../utils/progress') -exports.update = function(media, databasePath, callback) { - +exports.update = function (media, databasePath, callback) { var updateBar = null var emitter = null @@ -32,5 +30,4 @@ exports.update = function(media, databasePath, callback) { }) emitter.on('error', callback) - } diff --git a/src/input/output.js b/src/input/output.js index 1955880..eeef976 100644 --- a/src/input/output.js +++ b/src/input/output.js @@ -1,11 +1,12 @@ const debug = require('debug')('thumbsup') exports.paths = function (filepath, mediaType, config) { + var originals = false if (mediaType === 'image') { - var originals = config ? config.originalPhotos : false + originals = config ? config.originalPhotos : false return imageOutput(filepath, originals) } else if (mediaType === 'video') { - var originals = config ? config.originalVideos : false + originals = config ? config.originalVideos : false return videoOutput(filepath, originals) } else { debug(`Unsupported file type: ${mediaType}`) @@ -58,9 +59,9 @@ function videoOutput (filepath, originals) { } else { output.download = output.video } - return output; + return output } -function ext(file, ext) { +function ext (file, ext) { return file.replace(/\.[a-z0-9]+$/i, '.' + ext) } diff --git a/src/model/album.js b/src/model/album.js index f3658e1..09ad393 100644 --- a/src/model/album.js +++ b/src/model/album.js @@ -1,141 +1,141 @@ -var _ = require('lodash'); -var path = require('path'); -var url = require('url'); -var index = 0; +var _ = require('lodash') +var path = require('path') +var url = require('url') +var index = 0 // number of images to show in the album preview grid -var PREVIEW_COUNT = 10; +var PREVIEW_COUNT = 10 var SORT_ALBUMS_BY = { - 'title': function(album) { return album.title; }, - 'start-date': function(album) { return album.stats.fromDate; }, - 'end-date': function(album) { return album.stats.toDate; } -}; + 'title': function (album) { return album.title }, + 'start-date': function (album) { return album.stats.fromDate }, + 'end-date': function (album) { return album.stats.toDate } +} var SORT_MEDIA_BY = { - 'filename': function(file) { return file.filename; }, - 'date': function(file) { return file.date; } -}; + 'filename': function (file) { return file.filename }, + 'date': function (file) { return file.date } +} var PREVIEW_MISSING = { urls: { thumbnail: 'public/missing.png' } -}; +} -function Album(opts) { - if (typeof opts === 'string') opts = { title: opts }; - this.id = opts.id || ++index; - this.title = opts.title || ('Album ' + this.id); - this.basename = sanitise(this.title); - this.files = opts.files || []; - this.albums = opts.albums || []; - this.depth = 0; - this.home = false; - this.stats = null; - this.previews = null; - this.allFiles = []; +function Album (opts) { + if (typeof opts === 'string') opts = { title: opts } + this.id = opts.id || ++index + this.title = opts.title || ('Album ' + this.id) + this.basename = sanitise(this.title) + this.files = opts.files || [] + this.albums = opts.albums || [] + this.depth = 0 + this.home = false + this.stats = null + this.previews = null + this.allFiles = [] } -Album.prototype.finalize = function(options, parent) { - options = options || {}; - var albumsOutputFolder = options.albumsOutputFolder || '.'; +Album.prototype.finalize = function (options, parent) { + options = options || {} + var albumsOutputFolder = options.albumsOutputFolder || '.' // calculate final file paths and URLs if (parent == null) { - this.path = options.index; - this.url = options.index; - this.depth = 0; + this.path = options.index + this.url = options.index + this.depth = 0 } else { if (parent.depth > 0) { - this.basename = parent.basename + '-' + this.basename; + this.basename = parent.basename + '-' + this.basename } - this.path = path.join(albumsOutputFolder, this.basename + '.html'); - this.url = url.resolve(albumsOutputFolder + '/', this.basename + '.html'); - this.depth = parent.depth + 1; + this.path = path.join(albumsOutputFolder, this.basename + '.html') + this.url = url.resolve(albumsOutputFolder + '/', this.basename + '.html') + this.depth = parent.depth + 1 } // then finalize all nested albums (which uses the parent basename) for (var i = 0; i < this.albums.length; ++i) { - this.albums[i].finalize(options, this); + this.albums[i].finalize(options, this) } // perform stats & other calculations // once the nested albums have been finalized too - this.home = this.depth === 0; - this.calculateStats(); - this.calculateSummary(); - this.sort(options); - this.pickPreviews(); - this.aggregateAllFiles(); -}; + this.home = this.depth === 0 + this.calculateStats() + this.calculateSummary() + this.sort(options) + this.pickPreviews() + this.aggregateAllFiles() +} -Album.prototype.calculateStats = function() { +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'); + 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'); + 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, + 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; + toDate: _.max(_.compact(_.concat(nestedToDates, currentToDate))) + } + this.stats.total = this.stats.photos + this.stats.videos } -Album.prototype.calculateSummary = function() { +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(', '); -}; + ] + this.summary = _.compact(items).join(', ') +} -Album.prototype.sort = function(options) { - this.files = _.orderBy(this.files, SORT_MEDIA_BY[options.sortMediaBy], options.sortMediaDirection); - this.albums = _.orderBy(this.albums, SORT_ALBUMS_BY[options.sortAlbumsBy], options.sortAlbumsDirection); -}; +Album.prototype.sort = function (options) { + this.files = _.orderBy(this.files, SORT_MEDIA_BY[options.sortMediaBy], options.sortMediaDirection) + this.albums = _.orderBy(this.albums, SORT_ALBUMS_BY[options.sortAlbumsBy], options.sortAlbumsDirection) +} -Album.prototype.pickPreviews = function() { +Album.prototype.pickPreviews = function () { // also consider previews from nested albums - var nestedPicks = _.flatten(_.map(this.albums, 'previews')).filter(function(file) { - return file !== PREVIEW_MISSING; - }); + var nestedPicks = _.flatten(_.map(this.albums, 'previews')).filter(function (file) { + return file !== PREVIEW_MISSING + }) // then pick the top ones - var potentialPicks = _.concat(this.files, nestedPicks); - this.previews = potentialPicks.slice(0, PREVIEW_COUNT); + var potentialPicks = _.concat(this.files, nestedPicks) + this.previews = potentialPicks.slice(0, PREVIEW_COUNT) // and fill the gap with a placeholder - var missing = PREVIEW_COUNT - this.previews.length; + var missing = PREVIEW_COUNT - this.previews.length for (var i = 0; i < missing; ++i) { - this.previews.push(PREVIEW_MISSING); + this.previews.push(PREVIEW_MISSING) } -}; +} -Album.prototype.aggregateAllFiles = function() { +Album.prototype.aggregateAllFiles = function () { var nestedFiles = _.flatten(_.map(this.albums, 'allFiles')) - this.allFiles = _.concat(nestedFiles, this.files); -}; + this.allFiles = _.concat(nestedFiles, this.files) +} -function sanitise(filename) { - return filename.replace(/[^a-z0-9-_]/ig, ''); +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; +function itemCount (count, type) { + if (count === 0) return '' + var plural = (count > 1) ? 's' : '' + return '' + count + ' ' + type + plural } // for testing purposes -Album.resetIds = function() { - index = 0; -}; +Album.resetIds = function () { + index = 0 +} -module.exports = Album; +module.exports = Album diff --git a/src/model/by-date.js b/src/model/by-date.js index 34ba189..8bcb4fd 100644 --- a/src/model/by-date.js +++ b/src/model/by-date.js @@ -1,42 +1,42 @@ -var _ = require('lodash'); -var path = require('path'); -var moment = require('moment'); -var Album = require('./album'); +var _ = require('lodash') +var path = require('path') +var moment = require('moment') +var Album = require('./album') // creates nested albums based on the media date, e.g. "{year}/{month}" // opts = {format}, where format is a valid format // e.g. "YYYY-MM" or "YYYY/MMMM" for nested albums -exports.albums = function(collection, opts) { +exports.albums = function (collection, opts) { opts = _.defaults(opts, { grouping: opts.albumsDateFormat || 'YYYY-MMMM' - }); - var groups = {}; + }) + var groups = {} // put all files in the right albums - collection.forEach(function(media) { - var groupName = moment(media.date).format(opts.grouping); - createAlbumHierarchy(groups, groupName); - groups[groupName].files.push(media); - }); + collection.forEach(function (media) { + var groupName = moment(media.date).format(opts.grouping) + createAlbumHierarchy(groups, groupName) + groups[groupName].files.push(media) + }) // only return top-level albums - var topLevel = _.keys(groups).filter(function(dir) { - return path.dirname(dir) === '.'; - }); - return _.values(_.pick(groups, topLevel)); -}; + var topLevel = _.keys(groups).filter(function (dir) { + return path.dirname(dir) === '.' + }) + return _.values(_.pick(groups, topLevel)) +} -function createAlbumHierarchy(albumsByFullDate, dateSegment) { +function createAlbumHierarchy (albumsByFullDate, dateSegment) { if (!albumsByFullDate.hasOwnProperty(dateSegment)) { // create parent albums first - var parentDate = path.dirname(dateSegment); + var parentDate = path.dirname(dateSegment) if (parentDate !== '.') { - createAlbumHierarchy(albumsByFullDate, parentDate); + createAlbumHierarchy(albumsByFullDate, parentDate) } // then create album if it doesn't exist - var lastDateSegment = path.basename(dateSegment); - albumsByFullDate[dateSegment] = new Album({title: lastDateSegment}); + var lastDateSegment = path.basename(dateSegment) + albumsByFullDate[dateSegment] = new Album({title: lastDateSegment}) // then attach to parent if (parentDate !== '.') { - albumsByFullDate[parentDate].albums.push(albumsByFullDate[dateSegment]); + albumsByFullDate[parentDate].albums.push(albumsByFullDate[dateSegment]) } } } diff --git a/src/model/by-folder.js b/src/model/by-folder.js index a6c7390..f4f30cc 100644 --- a/src/model/by-folder.js +++ b/src/model/by-folder.js @@ -1,38 +1,38 @@ -var _ = require('lodash'); -var path = require('path'); -var Album = require('./album'); +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 albumsByFullPath = {}; +exports.albums = function (collection, opts) { + var albumsByFullPath = {} // put all files in the right album - collection.forEach(function(media) { - var fullDir = path.dirname(media.file.path); - createAlbumHierarchy(albumsByFullPath, fullDir); - albumsByFullPath[fullDir].files.push(media); - }); + collection.forEach(function (media) { + var fullDir = path.dirname(media.file.path) + createAlbumHierarchy(albumsByFullPath, fullDir) + albumsByFullPath[fullDir].files.push(media) + }) // only return top-level albums - var topLevel = _.keys(albumsByFullPath).filter(function(dir) { - return path.dirname(dir) === '.'; - }); - return _.values(_.pick(albumsByFullPath, topLevel)); -}; + var topLevel = _.keys(albumsByFullPath).filter(function (dir) { + return path.dirname(dir) === '.' + }) + return _.values(_.pick(albumsByFullPath, topLevel)) +} -function createAlbumHierarchy(albumsByFullPath, fullDir) { +function createAlbumHierarchy (albumsByFullPath, fullDir) { if (!albumsByFullPath.hasOwnProperty(fullDir)) { // create parent albums first - var parentDir = path.dirname(fullDir); + var parentDir = path.dirname(fullDir) if (parentDir !== '.') { - createAlbumHierarchy(albumsByFullPath, parentDir); + createAlbumHierarchy(albumsByFullPath, parentDir) } // then create album if it doesn't exist - var dirname = path.basename(fullDir); - albumsByFullPath[fullDir] = new Album({title: dirname}); + var dirname = path.basename(fullDir) + albumsByFullPath[fullDir] = new Album({title: dirname}) // then attach to parent if (parentDir !== '.') { - albumsByFullPath[parentDir].albums.push(albumsByFullPath[fullDir]); + albumsByFullPath[parentDir].albums.push(albumsByFullPath[fullDir]) } } } diff --git a/src/model/hierarchy.js b/src/model/hierarchy.js index e9b0653..3cabbb4 100644 --- a/src/model/hierarchy.js +++ b/src/model/hierarchy.js @@ -1,14 +1,8 @@ -var _ = require('lodash') -var gm = require('gm') -var pad = require('pad') -var path = require('path') var Album = require('./album') -var Media = require('./media') var byFolder = require('./by-folder') var byDate = require('./by-date') exports.createAlbums = function (collection, opts) { - // top-level album for the home page var home = new Album('Home') home.filename = opts.index || 'index' @@ -19,7 +13,7 @@ exports.createAlbums = function (collection, opts) { } else if (opts.albumsFrom === 'date') { home.albums = byDate.albums(collection, opts) } else { - throw 'Invalid option' + throw new Error('Invalid option') } // finalize all albums recursively (calculate stats, etc...) diff --git a/src/model/media.js b/src/model/media.js index 62bee0b..ee8b0b8 100644 --- a/src/model/media.js +++ b/src/model/media.js @@ -3,7 +3,7 @@ const moment = require('moment') const path = require('path') const EXIF_DATE_FORMAT = 'YYYY:MM:DD HH:mm:ssZ' -var index = 0; +var index = 0 /* View model for album entries diff --git a/src/output-media/resize.js b/src/output-media/resize.js index 7985f4f..995faab 100644 --- a/src/output-media/resize.js +++ b/src/output-media/resize.js @@ -6,7 +6,7 @@ const path = require('path') exports.sizes = { thumb: 120, - large: 1000, + large: 1000 } exports.copy = function (task, callback) { @@ -36,7 +36,7 @@ exports.photoLarge = function (task, callback) { // Web-streaming friendly video exports.videoWeb = function (task, callback) { - var ffmpeg = 'ffmpeg -i "' + task.src + '" -y "'+ task.dest +'" -f mp4 -vcodec libx264 -ab 96k' + var ffmpeg = 'ffmpeg -i "' + task.src + '" -y "' + task.dest + '" -f mp4 -vcodec libx264 -ab 96k' // AVCHD/MTS videos need a full-frame export to avoid interlacing artefacts if (path.extname(task.src).toLowerCase() === '.mts') { ffmpeg += ' -vf yadif=1 -qscale:v 4' @@ -49,10 +49,10 @@ exports.videoWeb = function (task, callback) { // Large video preview (before you click play) exports.videoLarge = function (task, callback) { async.series([ - function(next) { + function (next) { extractFrame(task, next) }, - function(next) { + function (next) { exports.photoLarge({ src: task.dest, dest: task.dest @@ -64,10 +64,10 @@ exports.videoLarge = function (task, callback) { // Small square video preview exports.videoSquare = function (task, callback) { async.series([ - function(next) { + function (next) { extractFrame(task, next) }, - function(next) { + function (next) { exports.photoSquare({ src: task.dest, dest: task.dest diff --git a/src/output-website/template.js b/src/output-website/template.js index 874d068..d2df553 100644 --- a/src/output-website/template.js +++ b/src/output-website/template.js @@ -1,64 +1,62 @@ -var fs = require('fs'); -var path = require('path'); -var handlebars = require('handlebars'); -var moment = require('moment'); +var fs = require('fs') +var path = require('path') +var handlebars = require('handlebars') +var moment = require('moment') -exports.create = function(options) { +exports.create = function (options) { + var DIR_TEMPLATES = path.join(__dirname, '..', '..', 'templates') + var DIR_THEME = path.join(DIR_TEMPLATES, 'themes', options.theme) - var DIR_TEMPLATES = path.join(__dirname, '..', '..', 'templates'); - var DIR_THEME = path.join(DIR_TEMPLATES, 'themes', options.theme); - - function isTemplate(filepath) { - return path.extname(filepath) === '.hbs'; + function isTemplate (filepath) { + return path.extname(filepath) === '.hbs' } - function compileTemplate(hbsFile) { - var src = fs.readFileSync(hbsFile); - return handlebars.compile(src.toString()); + function compileTemplate (hbsFile) { + var src = fs.readFileSync(hbsFile) + return handlebars.compile(src.toString()) } // main entry points var templates = { 'album': compileTemplate(path.join(DIR_TEMPLATES, 'album.hbs')) - }; + } // common partials - handlebars.registerPartial('analytics', compileTemplate(path.join(DIR_TEMPLATES, 'analytics.hbs'))); + handlebars.registerPartial('analytics', compileTemplate(path.join(DIR_TEMPLATES, 'analytics.hbs'))) // theme partials - var files = fs.readdirSync(DIR_THEME); - files.filter(isTemplate).forEach(function(filename) { - var templateName = path.basename(filename, path.extname(filename)); - handlebars.registerPartial(templateName, compileTemplate(path.join(DIR_THEME, filename))); + var files = fs.readdirSync(DIR_THEME) + files.filter(isTemplate).forEach(function (filename) { + var templateName = path.basename(filename, path.extname(filename)) + handlebars.registerPartial(templateName, compileTemplate(path.join(DIR_THEME, filename))) }) // utility helper // render a date in a legible format - handlebars.registerHelper('date', function(date) { - return moment(date).format('DD MMM YYYY'); - }); + handlebars.registerHelper('date', function (date) { + return moment(date).format('DD MMM YYYY') + }) // utility helper // render the first X items in an array - handlebars.registerHelper('slice', function(context, block) { - var ret = ""; - var count = parseInt(block.hash.count) || 1; - var i = 0; - var j = (count < context.length) ? count : context.length; - for(i,j; i': function (l, r) { return l > r; }, - '<=': function (l, r) { return l <= r; }, - '>=': function (l, r) { return l >= r; } - }; - if (!operators[operator]) { - throw new Error("Handlerbars Helper 'compare' doesn't know the operator " + operator); - } - result = operators[operator](lvalue, rvalue); - if (result) { - return options.fn(this); - } else { - return options.inverse(this); - } - }); + var operators, result + if (arguments.length < 3) { + throw new Error("Handlerbars Helper 'compare' needs 2 parameters") + } + if (options === undefined) { + options = rvalue + rvalue = operator + operator = '===' + } + operators = { + '==': function (l, r) { return l == r }, // eslint-disable-line eqeqeq + '===': function (l, r) { return l === r }, + '!=': function (l, r) { return l != r }, // eslint-disable-line eqeqeq + '!==': function (l, r) { return l !== r }, + '<': function (l, r) { return l < r }, + '>': function (l, r) { return l > r }, + '<=': function (l, r) { return l <= r }, + '>=': function (l, r) { return l >= r } + } + if (!operators[operator]) { + throw new Error(`Handlerbars Helper 'compare' doesn't know the operator ${operator}`) + } + result = operators[operator](lvalue, rvalue) + if (result) { + return options.fn(this) + } else { + return options.inverse(this) + } + }) // utility helper // return the relative path from the current folder to the argument - var currentFolder = '.'; - handlebars.registerHelper('relative', function(target, options) { - return path.relative(currentFolder, target); - }); + var currentFolder = '.' + handlebars.registerHelper('relative', function (target, options) { + return path.relative(currentFolder, target) + }) return { - render: function(template, data, folder) { - currentFolder = folder; - return templates[template](data); + render: function (template, data, folder) { + currentFolder = folder + return templates[template](data) } - }; - -}; + } +} diff --git a/src/output-website/website.js b/src/output-website/website.js index 1721cd4..f71811d 100644 --- a/src/output-website/website.js +++ b/src/output-website/website.js @@ -1,23 +1,17 @@ -var _ = require('lodash'); -var fs = require('fs-extra'); -var path = require('path'); -var async = require('async'); -var pad = require('pad'); -var less = require('less'); -var Album = require('../model/album'); -var byFolder = require('../model//by-folder'); -var byDate = require('../model//by-date'); -var template = require('./template'); +var fs = require('fs-extra') +var path = require('path') +var async = require('async') +var less = require('less') +var template = require('./template') -var DIR_PUBLIC = path.join(__dirname, '..', '..', 'public'); -var DIR_TEMPLATES = path.join(__dirname, '..', '..', 'templates'); - -exports.build = function(rootAlbum, opts, callback) { +var DIR_PUBLIC = path.join(__dirname, '..', '..', 'public') +var DIR_TEMPLATES = path.join(__dirname, '..', '..', 'templates') +exports.build = function (rootAlbum, opts, callback) { // create the right renderer (theme, download path, etc...) - var renderer = template.create(opts); + var renderer = template.create(opts) - function website(callback) { + function website (callback) { // create top level gallery var gallery = { home: rootAlbum, @@ -28,71 +22,71 @@ exports.build = function(rootAlbum, opts, callback) { thumbSize: opts.thumbSize, largeSize: opts.largeSize, googleAnalytics: opts.googleAnalytics - }; + } // render entire album hierarchy - var tasks = renderAlbum(gallery, [], rootAlbum); - async.parallel(tasks, callback); + var tasks = renderAlbum(gallery, [], rootAlbum) + async.parallel(tasks, callback) } - function renderAlbum(gallery, breadcrumbs, album) { + function renderAlbum (gallery, breadcrumbs, album) { // render this album var thisAlbumTask = renderTemplate(album.path, 'album', { gallery: gallery, breadcrumbs: breadcrumbs, album: album - }); - var tasks = [thisAlbumTask]; + }) + 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; + album.albums.forEach(function (nested) { + var nestedAlbumsTasks = renderAlbum(gallery, breadcrumbs.concat([album]), nested) + Array.prototype.push.apply(tasks, nestedAlbumsTasks) + }) + return tasks } - function renderTemplate(targetPath, templateName, data) { + function renderTemplate (targetPath, templateName, data) { // render a given HBS template - var fullPath = path.join(opts.output, targetPath); - var targetFolder = path.dirname(targetPath); - var contents = renderer.render(templateName, data, targetFolder); - return function(next) { + var fullPath = path.join(opts.output, targetPath) + var targetFolder = path.dirname(targetPath) + var contents = renderer.render(templateName, data, targetFolder) + return function (next) { fs.mkdirpSync(path.dirname(fullPath)) - fs.writeFile(fullPath, contents, next); - }; + fs.writeFile(fullPath, contents, next) + } } - function support(callback) { + function support (callback) { // copy all external JS/CSS - var dest = path.join(opts.output, 'public'); - fs.copy(DIR_PUBLIC, dest, callback); + var dest = path.join(opts.output, 'public') + fs.copy(DIR_PUBLIC, dest, callback) } - function lightGallery(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); + 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 videoJS (callback) { // copy VideoJS fonts that need to be one level above in a folder called "f" - var dest = path.join(opts.output, 'f'); - fs.copy(path.join(DIR_PUBLIC, 'f'), dest, callback); + var dest = path.join(opts.output, 'f') + fs.copy(path.join(DIR_PUBLIC, 'f'), dest, callback) } - function renderStyles(callback) { - var themeFile = path.join(DIR_TEMPLATES, 'themes', opts.theme, 'theme.less'); - var themeLess = fs.readFileSync(themeFile, 'utf-8'); + function renderStyles (callback) { + var themeFile = path.join(DIR_TEMPLATES, 'themes', opts.theme, 'theme.less') + var themeLess = fs.readFileSync(themeFile, 'utf-8') if (opts.css) { - themeLess += '\n' + fs.readFileSync(opts.css, 'utf-8'); + themeLess += '\n' + fs.readFileSync(opts.css, 'utf-8') } less.render(themeLess, function (err, output) { - if (err) return callback(err); - var dest = path.join(opts.output, 'public', 'style.css'); - fs.writeFile(dest, output.css, callback); - }); + if (err) return callback(err) + var dest = path.join(opts.output, 'public', 'style.css') + fs.writeFile(dest, output.css, callback) + }) } async.series([ @@ -101,8 +95,7 @@ exports.build = function(rootAlbum, opts, callback) { lightGallery, videoJS, renderStyles - ], function(err) { - callback(err); - }); - -}; + ], function (err) { + callback(err) + }) +} diff --git a/src/utils/progress.js b/src/utils/progress.js index 9d6bf61..24a3394 100644 --- a/src/utils/progress.js +++ b/src/utils/progress.js @@ -2,17 +2,18 @@ const pad = require('pad') const ProgressBar = require('progress') const util = require('util') -exports.create = function(message, count) { +exports.create = function (message, count) { + var format = '' if (typeof count === 'undefined') { - var format = pad(message, 20) + '[:bar] :eta' + format = pad(message, 20) + '[:bar] :eta' return new BetterProgressBar(format, 1) } if (Array.isArray(count)) count = count.length if (count > 0) { - var format = pad(message, 20) + '[:bar] :current/:total :eta' + format = pad(message, 20) + '[:bar] :current/:total :eta' return new BetterProgressBar(format, count) } else { - var format = pad(message, 20) + '[:bar] up to date' + format = pad(message, 20) + '[:bar] up to date' var bar = new BetterProgressBar(format, 1) bar.tick(1) return bar @@ -30,8 +31,8 @@ BetterProgressBar.prototype.eta = function () { var ratio = this.curr / this.total ratio = Math.min(Math.max(ratio, 0), 1) var percent = ratio * 100 - var elapsed = new Date - this.start - return (percent == 100) ? 0 : elapsed * (this.total / this.curr - 1) + var elapsed = new Date() - this.start + return (percent === 100) ? 0 : elapsed * ((this.total / this.curr) - 1) } BetterProgressBar.prototype.render = function (tokens) { @@ -44,15 +45,17 @@ BetterProgressBar.prototype.render = function (tokens) { } function formatEta (ms) { + var min = 0 + var sec = 0 if (isNaN(ms) || !isFinite(ms)) return '' if (ms > 60 * 1000) { - var min = Math.floor(ms / 60 / 1000) + min = Math.floor(ms / 60 / 1000) return `(${min.toFixed(0)}min left)` } else if (ms > 10 * 1000) { - var sec = Math.floor(ms / 10000) * 10 + sec = Math.floor(ms / 10000) * 10 return `(${sec.toFixed(0)}s left)` } else if (ms > 0) { - var sec = ms / 1000 + sec = ms / 1000 return `(a few seconds left)` } else { return 'done' diff --git a/test/fixtures.js b/test/fixtures.js index d6b887c..dc32163 100644 --- a/test/fixtures.js +++ b/test/fixtures.js @@ -1,4 +1,3 @@ -const File = require('../src/input/file') const Media = require('../src/model/media') exports.file = function (opts) { diff --git a/test/input/file.spec.js b/test/input/file.spec.js index 2d37307..a3168af 100644 --- a/test/input/file.spec.js +++ b/test/input/file.spec.js @@ -2,7 +2,6 @@ const should = require('should/as-function') const File = require('../../src/input/file') describe('Input file', function () { - it('reads the relative file path', function () { var file = new File(dbFile({ SourceFile: 'holidays/beach.jpg' @@ -36,13 +35,12 @@ describe('Input file', function () { })) should(file.type).eql('video') }) - }) function dbFile (data) { // some required data if (!data.SourceFile) data.SourceFile = 'photo.jpg' if (!data.File) data.File = {} - if (!data.File.FileModifyDate) data.File.FileModifyDate = '1999:12:31 23:59:59+00:00' + if (!data.File.FileModifyDate) data.File.FileModifyDate = '1999:12:31 23:59:59+00:00' return data } diff --git a/test/model/album-stats.spec.js b/test/model/album-stats.spec.js index c6fba1b..f306d57 100644 --- a/test/model/album-stats.spec.js +++ b/test/model/album-stats.spec.js @@ -1,58 +1,53 @@ -var should = require('should/as-function'); -var Album = require('../../src/model/album'); -var fixtures = require('../fixtures'); - -describe('Album', function() { - - describe('stats', function() { - - describe('single level stats', function() { - - it('has no nested albums', function() { - var a = new Album({}); - a.finalize(); - should(a.stats.albums).eql(0); +var should = require('should/as-function') +var Album = require('../../src/model/album') +var fixtures = require('../fixtures') + +describe('Album', function () { + describe('stats', function () { + describe('single level stats', function () { + it('has no nested albums', function () { + var a = new Album({}) + a.finalize() + should(a.stats.albums).eql(0) }) - it('calculates counts for a single level', function() { + it('calculates counts for a single level', function () { var a = new Album({ files: [ fixtures.photo(), fixtures.photo(), fixtures.photo(), fixtures.photo(), - fixtures.video(), fixtures.video(), + fixtures.video(), fixtures.video() ] - }); - a.finalize(); - should(a.stats.photos).eql(4); - should(a.stats.videos).eql(2); - }); + }) + a.finalize() + should(a.stats.photos).eql(4) + should(a.stats.videos).eql(2) + }) - it('calculates from/to dates', function() { + it('calculates from/to dates', function () { var a = new Album({ files: [ fixtures.photo({date: '2016-09-14'}), fixtures.photo({date: '2016-09-02'}), - fixtures.photo({date: '2016-10-21'}), + fixtures.photo({date: '2016-10-21'}) ] - }); - a.finalize(); - should(a.stats.fromDate).eql(fixtures.date('2016-09-02').getTime()); - should(a.stats.toDate).eql(fixtures.date('2016-10-21').getTime()); - }); - - }); - - describe('nested albums stats', function() { + }) + a.finalize() + should(a.stats.fromDate).eql(fixtures.date('2016-09-02').getTime()) + should(a.stats.toDate).eql(fixtures.date('2016-10-21').getTime()) + }) + }) - it('counts all nested albums', function() { + describe('nested albums stats', function () { + it('counts all nested albums', function () { var root = new Album({ albums: [new Album('a'), new Album('b')] - }); - root.finalize(); - should(root.stats.albums).eql(2); - }); + }) + root.finalize() + should(root.stats.albums).eql(2) + }) - it('counts all nested photos', function() { + it('counts all nested photos', function () { var root = new Album({ files: [fixtures.photo()], albums: [ @@ -60,12 +55,12 @@ describe('Album', function() { files: [fixtures.photo(), fixtures.photo()] }) ] - }); - root.finalize(); - should(root.stats.photos).eql(3); - }); + }) + root.finalize() + should(root.stats.photos).eql(3) + }) - it('counts all nested photos', function() { + it('counts all nested photos', function () { var root = new Album({ files: [fixtures.video()], albums: [ @@ -73,12 +68,12 @@ describe('Album', function() { files: [fixtures.video(), fixtures.video()] }) ] - }); - root.finalize(); - should(root.stats.videos).eql(3); - }); + }) + root.finalize() + should(root.stats.videos).eql(3) + }) - it('calculates from/to dates across all albums', function() { + it('calculates from/to dates across all albums', function () { var a = new Album({ files: [fixtures.photo({date: '2016-09-14'})], albums: [ @@ -89,79 +84,74 @@ describe('Album', function() { })] }) ] - }); - a.finalize(); - should(a.stats.fromDate).eql(fixtures.date('2016-09-02').getTime()); - should(a.stats.toDate).eql(fixtures.date('2016-10-21').getTime()); - }); - - }); - - }); - - describe('summary', function() { + }) + a.finalize() + should(a.stats.fromDate).eql(fixtures.date('2016-09-02').getTime()) + should(a.stats.toDate).eql(fixtures.date('2016-10-21').getTime()) + }) + }) + }) - it('creates a summary with a single photo', function() { - var a = new Album('single'); + describe('summary', function () { + it('creates a summary with a single photo', function () { + var a = new Album('single') a.files = [ fixtures.photo() - ]; - a.finalize(); + ] + a.finalize() should(a.summary).eql('1 photo') - }); + }) - it('creates a summary with a single video', function() { - var a = new Album('single'); + it('creates a summary with a single video', function () { + var a = new Album('single') a.files = [ fixtures.video() - ]; - a.finalize(); + ] + a.finalize() should(a.summary).eql('1 video') - }); + }) - it('creates a summary with a single album', function() { - var a = new Album('single'); - a.albums = [new Album('nested')]; - a.finalize(); + it('creates a summary with a single album', function () { + var a = new Album('single') + a.albums = [new Album('nested')] + a.finalize() should(a.summary).eql('1 album') - }); + }) - it('creates a summary with several photos', function() { - var a = new Album('single'); + it('creates a summary with several photos', function () { + var a = new Album('single') a.files = [ - fixtures.photo(), fixtures.photo(), - ]; - a.finalize(); + 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'); + it('creates a summary with several videos', function () { + var a = new Album('single') a.files = [ - fixtures.video(), fixtures.video(), - ]; - a.finalize(); + fixtures.video(), fixtures.video() + ] + a.finalize() should(a.summary).eql('2 videos') - }); + }) - it('creates a summary with several albums', function() { - var a = new Album('single'); - a.albums = [new Album('nested 1'), new Album('nested 2')]; - a.finalize(); + it('creates a summary with several albums', function () { + var a = new Album('single') + a.albums = [new Album('nested 1'), new Album('nested 2')] + a.finalize() should(a.summary).eql('2 albums') - }); + }) - it('creates a summary with a mix of albums, photos and videos', function() { - var a = new Album('single'); - a.albums = [new Album('nested')]; + it('creates a summary with a mix of albums, photos and videos', function () { + var a = new Album('single') + a.albums = [new Album('nested')] a.files = [ fixtures.photo(), fixtures.photo(), - fixtures.video(), fixtures.video(), - ]; - a.finalize(); + fixtures.video(), fixtures.video() + ] + a.finalize() should(a.summary).eql('1 album, 2 photos, 2 videos') - }); - - }); - -}); + }) + }) +}) diff --git a/test/model/album.spec.js b/test/model/album.spec.js index f0ad6f9..e0494f5 100644 --- a/test/model/album.spec.js +++ b/test/model/album.spec.js @@ -1,33 +1,29 @@ -var should = require('should/as-function'); -var Album = require('../../src/model/album'); -var fixtures = require('../fixtures'); -var path = require('path'); - -describe('Album', function() { - - describe('options', function() { - - it('can pass the title as a single argument', function() { - var a = new Album('Holidays'); - should(a.title).eql('Holidays'); - }); - - it('can pass a full hash of options', function() { - var a = new Album({id: 12, title: 'Holidays'}); - should(a.id).eql(12); - should(a.title).eql('Holidays'); - }); - - }); - - describe('output paths', function() { - - it('sanitises album titles for the file name', function() { - var a = new Album('hello & world'); - should(a.basename).eql('helloworld'); - }); - - it('concatenates nested filenames for uniqueness', function() { +var should = require('should/as-function') +var Album = require('../../src/model/album') +var fixtures = require('../fixtures') +var path = require('path') + +describe('Album', function () { + describe('options', function () { + it('can pass the title as a single argument', function () { + var a = new Album('Holidays') + should(a.title).eql('Holidays') + }) + + it('can pass a full hash of options', function () { + var a = new Album({id: 12, title: 'Holidays'}) + should(a.id).eql(12) + should(a.title).eql('Holidays') + }) + }) + + describe('output paths', function () { + it('sanitises album titles for the file name', function () { + var a = new Album('hello & world') + should(a.basename).eql('helloworld') + }) + + it('concatenates nested filenames for uniqueness', function () { // to avoid having two nested albums called "October" overwrite each other // note: doesn't use the root title to avoid "home-" or "index-" var root = new Album({ @@ -44,81 +40,79 @@ describe('Album', function() { albums: [ new Album({title: 'October'}) ] - }), + }) ] - }); - root.finalize(); - should(root.basename).eql('home'); - should(root.albums[0].basename).eql('2010'); - should(root.albums[1].basename).eql('2011'); - should(root.albums[0].albums[0].basename).eql('2010-October'); - should(root.albums[1].albums[0].basename).eql('2011-October'); - }); - - it('calculates the output file path', function() { + }) + root.finalize() + should(root.basename).eql('home') + should(root.albums[0].basename).eql('2010') + should(root.albums[1].basename).eql('2011') + should(root.albums[0].albums[0].basename).eql('2010-October') + should(root.albums[1].albums[0].basename).eql('2011-October') + }) + + it('calculates the output file path', function () { var root = new Album({ title: 'home', albums: [new Album({title: '2010'})] - }); - root.finalize({index: 'index.html'}); - should(root.path).eql('index.html'); - should(root.albums[0].path).eql('2010.html'); - }); + }) + root.finalize({index: 'index.html'}) + should(root.path).eql('index.html') + should(root.albums[0].path).eql('2010.html') + }) - it('calculates the URL for the browser', function() { + it('calculates the URL for the browser', function () { var root = new Album({ title: 'home', albums: [new Album({title: '2010'})] - }); - root.finalize({index: 'index.html'}); - should(root.url).eql('index.html'); - should(root.albums[0].url).eql('2010.html'); - }); + }) + root.finalize({index: 'index.html'}) + should(root.url).eql('index.html') + should(root.albums[0].url).eql('2010.html') + }) - it('calculates the output path with a target folder (slashes match the OS)', function() { + it('calculates the output path with a target folder (slashes match the OS)', function () { var root = new Album({ title: 'home', albums: [new Album({title: '2010'})] - }); - root.finalize({index: 'index.html', albumsOutputFolder: 'albums'}); - should(root.path).eql('index.html'); - should(root.albums[0].path).eql(path.join('albums', '2010.html')); - }); + }) + root.finalize({index: 'index.html', albumsOutputFolder: 'albums'}) + should(root.path).eql('index.html') + should(root.albums[0].path).eql(path.join('albums', '2010.html')) + }) - it('calculates the URL with a target folder (always forward slashes)', function() { + it('calculates the URL with a target folder (always forward slashes)', function () { var root = new Album({ title: 'home', albums: [new Album({title: '2010'})] - }); - root.finalize({index: 'index.html', albumsOutputFolder: 'albums'}); - should(root.path).eql('index.html'); - should(root.albums[0].path).eql('albums/2010.html'); - }); - - }); - - describe('previews', function() { - - it('picks the first 10 files as previews', function() { + }) + root.finalize({index: 'index.html', albumsOutputFolder: 'albums'}) + should(root.path).eql('index.html') + should(root.albums[0].path).eql('albums/2010.html') + }) + }) + + describe('previews', function () { + it('picks the first 10 files as previews', function () { var a = new Album({files: [ fixtures.photo(), fixtures.photo(), fixtures.photo(), fixtures.photo(), fixtures.photo(), fixtures.photo(), fixtures.photo(), fixtures.photo(), - fixtures.photo(), fixtures.photo(), fixtures.photo(), fixtures.photo(), - ]}); - a.finalize(); - should(a.previews).have.length(10); - }); + fixtures.photo(), fixtures.photo(), fixtures.photo(), fixtures.photo() + ]}) + a.finalize() + should(a.previews).have.length(10) + }) - it('adds thumbnails to fill', function() { + it('adds thumbnails to fill', function () { var a = new Album({files: [ - fixtures.photo(), fixtures.photo(), - ]}); - a.finalize(); - should(a.previews[2].urls.thumbnail).eql('public/missing.png'); - should(a.previews[9].urls.thumbnail).eql('public/missing.png'); - }); - - it('uses files from nested albums too', function() { + fixtures.photo(), fixtures.photo() + ]}) + a.finalize() + should(a.previews[2].urls.thumbnail).eql('public/missing.png') + should(a.previews[9].urls.thumbnail).eql('public/missing.png') + }) + + it('uses files from nested albums too', function () { var a = new Album({ title: 'a', albums: [ @@ -131,125 +125,120 @@ describe('Album', function() { files: [fixtures.photo(), fixtures.photo()] }) ] - }); - a.finalize(); - should(a.previews).have.length(10); + }) + a.finalize() + should(a.previews).have.length(10) for (var i = 0; i < 4; ++i) { - should(a.previews[i].urls.thumbnail).not.eql('public/missing.png'); + should(a.previews[i].urls.thumbnail).not.eql('public/missing.png') } - }); - - }); - - describe('sorting', function() { - - it('can sort albums by title', function() { - var a = new Album('A'); - var b = new Album('B'); - var c = new Album('C'); - var root = new Album({albums: [c, a, b]}); - root.finalize({sortAlbumsBy: 'title'}); - should(root.albums).eql([a, b, c]); - }); - - it('can sort albums by start date', function() { - var startJan = albumWithFileDates(['2010-01-01', '2010-05-01']); - var startFeb = albumWithFileDates(['2010-02-01', '2010-04-01']); - var startMar = albumWithFileDates(['2010-03-01', '2010-03-01']); - var root = new Album({albums: [startFeb, startMar, startJan]}); - root.finalize({sortAlbumsBy: 'start-date'}); - should(root.albums).eql([startJan, startFeb, startMar]); - }); - - it('can sort albums by end date', function() { - var endMay = albumWithFileDates(['2010-01-01', '2010-05-01']); - var endApr = albumWithFileDates(['2010-02-01', '2010-04-01']); - var endMar = albumWithFileDates(['2010-03-01', '2010-03-01']); - var root = new Album({albums: [endMay, endMar, endApr]}); - root.finalize({sortAlbumsBy: 'end-date'}); - should(root.albums).eql([endMar, endApr, endMay]); - }); - - it('can sort media by filename', function() { - var a = fixtures.photo({path: 'a'}); - var b = fixtures.photo({path: 'b'}); - var c = fixtures.photo({path: 'c'}); - var album = new Album({files: [c, a, b]}); - album.finalize({sortMediaBy: 'filename'}); - should(album.files).eql([a, b, c]); - }); - - it('can sort media by reverse filename', function() { - var a = fixtures.photo({path: 'a'}); - var b = fixtures.photo({path: 'b'}); - var c = fixtures.photo({path: 'c'}); - var album = new Album({files: [c, a, b]}); - album.finalize({sortMediaBy: 'filename', sortMediaDirection: 'desc'}); - should(album.files).eql([c, b, a]); - }); - - it('sorts nested albums too', function() { - var nested = new Album({title: 'nested', files: [ - fixtures.photo({path: 'b'}), - fixtures.photo({path: 'a'}), - ]}); - var root = new Album({title: 'home', albums: [nested]}); - root.finalize({sortMediaBy: 'filename'}); - should(nested.files[0].file.path).eql('a'); - should(nested.files[1].file.path).eql('b'); - }); - - }); - - describe('nested albums basic logic', function() { - - it('calculates the depth of every album', function() { - var a = new Album('single'); - var b = new Album('single'); - var c = new Album('single'); - var d = new Album('single'); - a.albums = [b, c]; - c.albums = [d]; - a.finalize(); - should(a.depth).eql(0); - should(b.depth).eql(1); - should(c.depth).eql(1); - should(d.depth).eql(2); - }); - - it('sets the home flag on the top-level album', function() { - var a = new Album('single'); - var b = new Album('single'); - var c = new Album('single'); - var d = new Album('single'); - a.albums = [b, c]; - c.albums = [d]; - a.finalize(); - should(a.home).eql(true); - should(b.home).eql(false); - should(c.home).eql(false); - should(d.home).eql(false); - }); - - it('passes finalising options to all nested albums (e.g. sorting)', function() { - var nested = new Album({title: 'nested', files: [ - fixtures.photo({path: 'b'}), - fixtures.photo({path: 'a'}), - ]}); - var root = new Album({title: 'home', albums: [nested]}); - root.finalize({sortMediaBy: 'filename'}); - should(nested.files[0].file.path).eql('a'); - should(nested.files[1].file.path).eql('b'); - }); - - }); - -}); - - -function albumWithFileDates(dates) { - var files = dates.map(function(d) { - return fixtures.photo({date: d}); - }); - return new Album({files: files}); + }) + }) + + describe('sorting', function () { + it('can sort albums by title', function () { + var a = new Album('A') + var b = new Album('B') + var c = new Album('C') + var root = new Album({albums: [c, a, b]}) + root.finalize({sortAlbumsBy: 'title'}) + should(root.albums).eql([a, b, c]) + }) + + it('can sort albums by start date', function () { + var startJan = albumWithFileDates(['2010-01-01', '2010-05-01']) + var startFeb = albumWithFileDates(['2010-02-01', '2010-04-01']) + var startMar = albumWithFileDates(['2010-03-01', '2010-03-01']) + var root = new Album({albums: [startFeb, startMar, startJan]}) + root.finalize({sortAlbumsBy: 'start-date'}) + should(root.albums).eql([startJan, startFeb, startMar]) + }) + + it('can sort albums by end date', function () { + var endMay = albumWithFileDates(['2010-01-01', '2010-05-01']) + var endApr = albumWithFileDates(['2010-02-01', '2010-04-01']) + var endMar = albumWithFileDates(['2010-03-01', '2010-03-01']) + var root = new Album({albums: [endMay, endMar, endApr]}) + root.finalize({sortAlbumsBy: 'end-date'}) + should(root.albums).eql([endMar, endApr, endMay]) + }) + + it('can sort media by filename', function () { + var a = fixtures.photo({path: 'a'}) + var b = fixtures.photo({path: 'b'}) + var c = fixtures.photo({path: 'c'}) + var album = new Album({files: [c, a, b]}) + album.finalize({sortMediaBy: 'filename'}) + should(album.files).eql([a, b, c]) + }) + + it('can sort media by reverse filename', function () { + var a = fixtures.photo({path: 'a'}) + var b = fixtures.photo({path: 'b'}) + var c = fixtures.photo({path: 'c'}) + var album = new Album({files: [c, a, b]}) + album.finalize({sortMediaBy: 'filename', sortMediaDirection: 'desc'}) + should(album.files).eql([c, b, a]) + }) + + it('sorts nested albums too', function () { + var nested = new Album({title: 'nested', + files: [ + fixtures.photo({path: 'b'}), + fixtures.photo({path: 'a'}) + ]}) + var root = new Album({title: 'home', albums: [nested]}) + root.finalize({sortMediaBy: 'filename'}) + should(nested.files[0].file.path).eql('a') + should(nested.files[1].file.path).eql('b') + }) + }) + + describe('nested albums basic logic', function () { + it('calculates the depth of every album', function () { + var a = new Album('single') + var b = new Album('single') + var c = new Album('single') + var d = new Album('single') + a.albums = [b, c] + c.albums = [d] + a.finalize() + should(a.depth).eql(0) + should(b.depth).eql(1) + should(c.depth).eql(1) + should(d.depth).eql(2) + }) + + it('sets the home flag on the top-level album', function () { + var a = new Album('single') + var b = new Album('single') + var c = new Album('single') + var d = new Album('single') + a.albums = [b, c] + c.albums = [d] + a.finalize() + should(a.home).eql(true) + should(b.home).eql(false) + should(c.home).eql(false) + should(d.home).eql(false) + }) + + it('passes finalising options to all nested albums (e.g. sorting)', function () { + var nested = new Album({title: 'nested', + files: [ + fixtures.photo({path: 'b'}), + fixtures.photo({path: 'a'}) + ]}) + var root = new Album({title: 'home', albums: [nested]}) + root.finalize({sortMediaBy: 'filename'}) + should(nested.files[0].file.path).eql('a') + should(nested.files[1].file.path).eql('b') + }) + }) +}) + +function albumWithFileDates (dates) { + var files = dates.map(function (d) { + return fixtures.photo({date: d}) + }) + return new Album({files: files}) } diff --git a/test/model/by-date.spec.js b/test/model/by-date.spec.js index 6f641e1..0ca47f5 100644 --- a/test/model/by-date.spec.js +++ b/test/model/by-date.spec.js @@ -1,25 +1,26 @@ -var should = require('should/as-function'); -var Album = require('../../src/model/album.js'); -var bydate = require('../../src/model/by-date.js'); -var fixtures = require('../fixtures'); +/* eslint-disable camelcase */ -describe('ByDate', function() { +var should = require('should/as-function') +var Album = require('../../src/model/album.js') +var bydate = require('../../src/model/by-date.js') +var fixtures = require('../fixtures') - beforeEach(function() { - Album.resetIds(); - }); +describe('ByDate', function () { + beforeEach(function () { + Album.resetIds() + }) it('creates top-level albums grouped by month', function () { // create files from different dates - var a_2016_06 = fixtures.photo({date: fixtures.date('2016-06-01')}); - var b_2016_06 = fixtures.photo({date: fixtures.date('2016-06-10')}); - var c_2016_07 = fixtures.photo({date: fixtures.date('2016-07-23')}); - var d_2016_07 = fixtures.video({date: fixtures.date('2016-07-18')}); + var a_2016_06 = fixtures.photo({date: fixtures.date('2016-06-01')}) + var b_2016_06 = fixtures.photo({date: fixtures.date('2016-06-10')}) + var c_2016_07 = fixtures.photo({date: fixtures.date('2016-07-23')}) + var d_2016_07 = fixtures.video({date: fixtures.date('2016-07-18')}) // group them per month var collection = [a_2016_06, b_2016_06, c_2016_07, d_2016_07] var albums = bydate.albums(collection, { grouping: 'YYYY-MM' - }); + }) // assert on the result should(albums).eql([ new Album({ @@ -32,20 +33,20 @@ describe('ByDate', function() { title: '2016-07', files: [c_2016_07, d_2016_07] }) - ]); - }); + ]) + }) it('creates albums using a date hierarchy', function () { // create files from different dates - var a_2015_06 = fixtures.photo({date: fixtures.date('2015-06-01')}); - var b_2015_06 = fixtures.photo({date: fixtures.date('2015-06-10')}); - var c_2016_07 = fixtures.photo({date: fixtures.date('2016-07-23')}); - var d_2016_08 = fixtures.video({date: fixtures.date('2016-08-18')}); + var a_2015_06 = fixtures.photo({date: fixtures.date('2015-06-01')}) + var b_2015_06 = fixtures.photo({date: fixtures.date('2015-06-10')}) + var c_2016_07 = fixtures.photo({date: fixtures.date('2016-07-23')}) + var d_2016_08 = fixtures.video({date: fixtures.date('2016-08-18')}) // group them per year, and nested month var collection = [a_2015_06, b_2015_06, c_2016_07, d_2016_08] var albums = bydate.albums(collection, { grouping: 'YYYY/MM' - }); + }) // assert on the result should(albums).eql([ new Album({ @@ -77,7 +78,6 @@ describe('ByDate', function() { }) ] }) - ]); - }); - -}); + ]) + }) +}) diff --git a/test/model/by-folder.spec.js b/test/model/by-folder.spec.js index c726132..1f066b2 100644 --- a/test/model/by-folder.spec.js +++ b/test/model/by-folder.spec.js @@ -1,23 +1,22 @@ -var should = require('should/as-function'); -var Album = require('../../src/model/album.js'); -var byfolder = require('../../src/model/by-folder.js'); -var fixtures = require('../fixtures'); +var should = require('should/as-function') +var Album = require('../../src/model/album.js') +var byfolder = require('../../src/model/by-folder.js') +var fixtures = require('../fixtures') -describe('ByFolder', function() { - - beforeEach(function() { - Album.resetIds(); - }); +describe('ByFolder', function () { + beforeEach(function () { + Album.resetIds() + }) 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'}); + 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 = [london1, london2, newyork1, newyork2] - var albums = byfolder.albums(collection, {}); + var albums = byfolder.albums(collection, {}) // assert on the result should(albums).eql([ new Album({ @@ -30,16 +29,16 @@ describe('ByFolder', function() { title: 'newyork', files: [newyork1, newyork2] }) - ]); - }); + ]) + }) it('creates nested albums for nested folders', function () { // create files in nested folders - var photo1 = fixtures.photo({path: 'a/b/c/IMG_000001.jpg'}); - var photo2 = fixtures.photo({path: 'a/d/IMG_000002.jpg'}); + var photo1 = fixtures.photo({path: 'a/b/c/IMG_000001.jpg'}) + var photo2 = fixtures.photo({path: 'a/d/IMG_000002.jpg'}) // group them per folder var collection = [photo1, photo2] - var albums = byfolder.albums(collection, {}); + var albums = byfolder.albums(collection, {}) // assert on the result should(albums).eql([ new Album({ @@ -66,7 +65,6 @@ describe('ByFolder', function() { }) ] }) - ]); - }); - -}); + ]) + }) +}) diff --git a/test/model/media.spec.js b/test/model/media.spec.js index f0680dc..49b4c70 100644 --- a/test/model/media.spec.js +++ b/test/model/media.spec.js @@ -1,9 +1,8 @@ -var should = require('should/as-function'); -var Media = require('../../src/model/media'); -var fixtures = require('../fixtures'); +var should = require('should/as-function') +var Media = require('../../src/model/media') +var fixtures = require('../fixtures') describe('Media', function () { - describe('date taken', function () { it('reads the EXIF date if present', function () { const file = fixtures.file() @@ -20,7 +19,7 @@ describe('Media', function () { }) describe('photos and videos', function () { - it('can tell if a file is a regular photo', function() { + it('can tell if a file is a regular photo', function () { const file = fixtures.file({type: 'image'}) file.meta.File.MIMEType = 'image/jpeg' const media = new Media(file) @@ -28,7 +27,7 @@ describe('Media', function () { should(media.isAnimated).eql(false) }) - it('can tell if a file is a non-animated gif', function() { + it('can tell if a file is a non-animated gif', function () { const file = fixtures.file({type: 'image'}) file.meta.File.MIMEType = 'image/gif' const media = new Media(file) @@ -36,7 +35,7 @@ describe('Media', function () { should(media.isAnimated).eql(false) }) - it('can tell if a file is an animated gif', function() { + it('can tell if a file is an animated gif', function () { const file = fixtures.file({type: 'image'}) file.meta.File.MIMEType = 'image/gif' file.meta.GIF = {FrameCount: 10} @@ -45,7 +44,7 @@ describe('Media', function () { should(media.isAnimated).eql(true) }) - it('can tell if a file is a video', function() { + it('can tell if a file is a video', function () { const file = fixtures.file({type: 'video'}) const media = new Media(file) should(media.isVideo).eql(true) @@ -53,7 +52,7 @@ describe('Media', function () { }) }) - describe('caption', function() { + describe('caption', function () { it('uses the EXIF caption if present', function () { const file = fixtures.file() file.meta.EXIF['ImageDescription'] = 'some caption' @@ -76,5 +75,4 @@ describe('Media', function () { should(media.caption).eql('exif caption') }) }) - })