mirror of
https://github.com/thumbsup/thumbsup
synced 2024-11-03 15:40:14 +00:00
Fix #61: new options to avoid copying original photos to the output folder
This commit is contained in:
parent
92706276a0
commit
80f7a88c35
@ -62,8 +62,9 @@ Required:
|
||||
Output options:
|
||||
--thumb-size Pixel size of the square thumbnails [number] [default: 120]
|
||||
--large-size Pixel height of the fullscreen photos [number] [default: 1000]
|
||||
--original-photos Copy and allow download of full-size photos [boolean] [default: false]
|
||||
--original-videos Copy and allow download of full-size videos [boolean] [default: false]
|
||||
--download-photos Target of the photo download links [choices: "large", "copy", "symlink", "link"] [default: "large"]
|
||||
--download-videos Target of the video download links [choices: "large", "copy", "symlink", "link"] [default: "large"]
|
||||
--download-link-prefix Path or URL prefix for linked downloads [string]
|
||||
--cleanup Remove any output file that's no longer needed [boolean] [default: false]
|
||||
|
||||
Album options:
|
||||
@ -83,6 +84,10 @@ Website options:
|
||||
--css Path to a custom provided CSS/LESS file for styling [string]
|
||||
--google-analytics Code for Google Analytics tracking [string]
|
||||
|
||||
Deprecated:
|
||||
--original-photos Copy and allow download of full-size photos [boolean] [default: false]
|
||||
--original-videos Copy and allow download of full-size videos [boolean] [default: false]
|
||||
|
||||
Options:
|
||||
--help Show help [boolean]
|
||||
--config Path to JSON config file [string]
|
||||
|
@ -46,17 +46,22 @@ var opts = yargs
|
||||
type: 'number',
|
||||
'default': 1000
|
||||
},
|
||||
'original-photos': {
|
||||
'download-photos': {
|
||||
group: 'Output options:',
|
||||
description: 'Copy and allow download of full-size photos',
|
||||
type: 'boolean',
|
||||
'default': false
|
||||
description: 'Target of the photo download links',
|
||||
choices: ['large', 'copy', 'symlink', 'link'],
|
||||
'default': 'large'
|
||||
},
|
||||
'original-videos': {
|
||||
'download-videos': {
|
||||
group: 'Output options:',
|
||||
description: 'Copy and allow download of full-size videos',
|
||||
type: 'boolean',
|
||||
'default': false
|
||||
description: 'Target of the video download links',
|
||||
choices: ['large', 'copy', 'symlink', 'link'],
|
||||
'default': 'large'
|
||||
},
|
||||
'download-link-prefix': {
|
||||
group: 'Output options:',
|
||||
description: 'Path or URL prefix for linked downloads',
|
||||
type: 'string'
|
||||
},
|
||||
'cleanup': {
|
||||
group: 'Output options:',
|
||||
@ -153,6 +158,23 @@ var opts = yargs
|
||||
'config': {
|
||||
description: 'JSON config file (one key per argument)',
|
||||
normalize: true
|
||||
},
|
||||
|
||||
// ------------------------------------
|
||||
// Deprecated options
|
||||
// ------------------------------------
|
||||
|
||||
'original-photos': {
|
||||
group: 'Deprecated:',
|
||||
description: 'Copy and allow download of full-size photos',
|
||||
type: 'boolean',
|
||||
'default': false
|
||||
},
|
||||
'original-videos': {
|
||||
group: 'Deprecated:',
|
||||
description: 'Copy and allow download of full-size videos',
|
||||
type: 'boolean',
|
||||
'default': false
|
||||
}
|
||||
|
||||
})
|
||||
@ -162,15 +184,27 @@ var opts = yargs
|
||||
'{ "sort-albums-by": "start-date" }')
|
||||
.argv
|
||||
|
||||
// Post-processing and smart defaults
|
||||
opts['input'] = path.resolve(opts['input'])
|
||||
opts['output'] = path.resolve(opts['output'])
|
||||
if (!opts['download-link-prefix']) {
|
||||
opts['download-link-prefix'] = path.relative(opts['output'], opts['input'])
|
||||
}
|
||||
|
||||
// Convert deprecated options to the new replacement
|
||||
if (opts['original-photos']) opts['download-photos'] = 'copy'
|
||||
if (opts['original-videos']) opts['download-videos'] = 'copy'
|
||||
|
||||
index.build({
|
||||
input: path.resolve(opts['input']),
|
||||
output: path.resolve(opts['output']),
|
||||
input: opts['input'],
|
||||
output: opts['output'],
|
||||
cleanup: opts['cleanup'],
|
||||
title: opts['title'],
|
||||
thumbSize: opts['thumb-size'],
|
||||
largeSize: opts['large-size'],
|
||||
originalPhotos: opts['original-photos'],
|
||||
originalVideos: opts['original-videos'],
|
||||
downloadPhotos: opts['download-photos'],
|
||||
downloadVideos: opts['download-videos'],
|
||||
downloadLinkPrefix: opts['download-link-prefix'],
|
||||
albumsFrom: opts['albums-from'],
|
||||
albumsDateFormat: opts['albums-date-format'],
|
||||
sortAlbumsBy: opts['sort-albums-by'],
|
||||
|
@ -39,6 +39,7 @@
|
||||
"moment": "^2.16.0",
|
||||
"pad": "^1.0.2",
|
||||
"progress": "~1.1.8",
|
||||
"url-join": "^2.0.2",
|
||||
"video.js": "^5.17.0",
|
||||
"yargs": "^6.3.0"
|
||||
},
|
||||
|
@ -13,7 +13,7 @@ function File (dbEntry, opts) {
|
||||
this.path = dbEntry.SourceFile
|
||||
this.date = fileDate(dbEntry)
|
||||
this.type = mediaType(dbEntry)
|
||||
this.output = output.paths(this.path, this.type, opts)
|
||||
this.output = output.paths(this.path, this.type, opts || {})
|
||||
}
|
||||
|
||||
function fileDate (dbEntry) {
|
||||
|
@ -1,20 +1,21 @@
|
||||
const debug = require('debug')('thumbsup')
|
||||
const path = require('path')
|
||||
const urljoin = require('url-join')
|
||||
|
||||
exports.paths = function (filepath, mediaType, config) {
|
||||
var originals = false
|
||||
if (mediaType === 'image') {
|
||||
originals = config ? config.originalPhotos : false
|
||||
return imageOutput(filepath, originals)
|
||||
// originals = config ? config.originalPhotos : false
|
||||
return imageOutput(filepath, config)
|
||||
} else if (mediaType === 'video') {
|
||||
originals = config ? config.originalVideos : false
|
||||
return videoOutput(filepath, originals)
|
||||
// originals = config ? config.originalVideos : false
|
||||
return videoOutput(filepath, config)
|
||||
} else {
|
||||
debug(`Unsupported file type: ${mediaType}`)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function imageOutput (filepath, originals) {
|
||||
function imageOutput (filepath, config) {
|
||||
const output = {
|
||||
thumbnail: {
|
||||
path: 'media/thumbs/' + filepath,
|
||||
@ -25,18 +26,11 @@ function imageOutput (filepath, originals) {
|
||||
rel: 'photo:large'
|
||||
}
|
||||
}
|
||||
if (originals) {
|
||||
output.download = {
|
||||
path: 'media/original/' + filepath,
|
||||
rel: 'original'
|
||||
}
|
||||
} else {
|
||||
output.download = output.large
|
||||
}
|
||||
setDownload(filepath, config, 'image', output)
|
||||
return output
|
||||
}
|
||||
|
||||
function videoOutput (filepath, originals) {
|
||||
function videoOutput (filepath, config) {
|
||||
var output = {
|
||||
thumbnail: {
|
||||
path: 'media/thumbs/' + ext(filepath, 'jpg'),
|
||||
@ -51,17 +45,46 @@ function videoOutput (filepath, originals) {
|
||||
rel: 'video:resized'
|
||||
}
|
||||
}
|
||||
if (originals) {
|
||||
output.download = {
|
||||
path: 'media/original/' + filepath,
|
||||
rel: 'original'
|
||||
}
|
||||
} else {
|
||||
output.download = output.video
|
||||
}
|
||||
setDownload(filepath, config, 'video', output)
|
||||
return output
|
||||
}
|
||||
|
||||
function setDownload (filepath, config, type, output) {
|
||||
const configKey = (type === 'image' ? 'downloadPhotos' : 'downloadVideos')
|
||||
const largeVersion = (type === 'image' ? output.large : output.video)
|
||||
switch (config[configKey]) {
|
||||
case 'large':
|
||||
output.download = largeVersion
|
||||
break
|
||||
case 'copy':
|
||||
output.download = {
|
||||
path: path.join('media', 'original', filepath),
|
||||
rel: 'fs:copy'
|
||||
}
|
||||
break
|
||||
case 'symlink':
|
||||
output.download = {
|
||||
path: path.join('media', 'original', filepath),
|
||||
rel: 'fs:symlink'
|
||||
}
|
||||
break
|
||||
case 'link':
|
||||
output.download = {
|
||||
path: join(config.downloadLinkPrefix, filepath),
|
||||
rel: 'fs:link'
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
function ext (file, ext) {
|
||||
return file.replace(/\.[a-z0-9]+$/i, '.' + ext)
|
||||
}
|
||||
|
||||
function join (prefix, filepath) {
|
||||
if (prefix.match(/^https?:\/\//)) {
|
||||
return urljoin(prefix, filepath)
|
||||
} else {
|
||||
return path.join(prefix, filepath)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
const async = require('async')
|
||||
const childProcess = require('child_process')
|
||||
const fs = require('fs-extra')
|
||||
const gm = require('gm')
|
||||
const path = require('path')
|
||||
|
||||
@ -9,10 +8,6 @@ exports.sizes = {
|
||||
large: 1000
|
||||
}
|
||||
|
||||
exports.copy = function (task, callback) {
|
||||
fs.copy(task.src, task.dest, callback)
|
||||
}
|
||||
|
||||
// Small square photo thumbnail
|
||||
exports.photoSquare = function (task, callback) {
|
||||
gm(task.src)
|
||||
|
@ -3,8 +3,17 @@ const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const resize = require('./resize')
|
||||
|
||||
function copy (task, callback) {
|
||||
fs.copy(task.src, task.dest, callback)
|
||||
}
|
||||
|
||||
function symlink (task, callback) {
|
||||
fs.symlink(task.src, task.dest, callback)
|
||||
}
|
||||
|
||||
const ACTION_MAP = {
|
||||
'original': resize.copy,
|
||||
'fs:copy': copy,
|
||||
'fs:symlink': symlink,
|
||||
'photo:thumbnail': resize.photoSquare,
|
||||
'photo:large': resize.photoLarge,
|
||||
'video:thumbnail': resize.videoSquare,
|
||||
@ -26,8 +35,9 @@ exports.create = function (opts, files, filterType) {
|
||||
var src = path.join(opts.input, f.path)
|
||||
var dest = path.join(opts.output, f.output[out].path)
|
||||
var destDate = modifiedDate(dest)
|
||||
if (f.date > destDate) {
|
||||
var action = ACTION_MAP[f.output[out].rel]
|
||||
// ignore output files that don't have an action (e.g. existing links)
|
||||
if (action && f.date > destDate) {
|
||||
tasks[dest] = (done) => {
|
||||
fs.mkdirsSync(path.dirname(dest))
|
||||
debug(`${f.output[out].rel} from ${src} to ${dest}`)
|
||||
|
198
test/input/output.spec.js
Normal file
198
test/input/output.spec.js
Normal file
@ -0,0 +1,198 @@
|
||||
const should = require('should/as-function')
|
||||
const output = require('../../src/input/output')
|
||||
|
||||
describe('Output paths', function () {
|
||||
describe('Images', function () {
|
||||
it('generates a thumbnail', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {})
|
||||
should(o.thumbnail).eql({
|
||||
path: 'media/thumbs/holidays/beach.jpg',
|
||||
rel: 'photo:thumbnail'
|
||||
})
|
||||
})
|
||||
|
||||
it('generates a large "web" version', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {})
|
||||
should(o.large).eql({
|
||||
path: 'media/large/holidays/beach.jpg',
|
||||
rel: 'photo:large'
|
||||
})
|
||||
})
|
||||
|
||||
it('can point downloads to the large version', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {
|
||||
downloadPhotos: 'large'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: 'media/large/holidays/beach.jpg',
|
||||
rel: 'photo:large'
|
||||
})
|
||||
})
|
||||
|
||||
it('can point downloads to a copy in the output folder', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {
|
||||
downloadPhotos: 'copy'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: 'media/original/holidays/beach.jpg',
|
||||
rel: 'fs:copy'
|
||||
})
|
||||
})
|
||||
|
||||
it('can point downloads to a symlink to the originals', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {
|
||||
downloadPhotos: 'symlink'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: 'media/original/holidays/beach.jpg',
|
||||
rel: 'fs:symlink'
|
||||
})
|
||||
})
|
||||
|
||||
it('can point downloads to an existing link', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {
|
||||
downloadPhotos: 'link',
|
||||
downloadLinkPrefix: '../myphotos'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: '../myphotos/holidays/beach.jpg',
|
||||
rel: 'fs:link'
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Videos', function () {
|
||||
it('generates a thumbnail', function () {
|
||||
var o = output.paths('holidays/seagull.mp4', 'video', {})
|
||||
should(o.thumbnail).eql({
|
||||
path: 'media/thumbs/holidays/seagull.jpg',
|
||||
rel: 'video:thumbnail'
|
||||
})
|
||||
})
|
||||
|
||||
it('generates a poster image', function () {
|
||||
var o = output.paths('holidays/seagull.mp4', 'video', {})
|
||||
should(o.large).eql({
|
||||
path: 'media/large/holidays/seagull.jpg',
|
||||
rel: 'video:poster'
|
||||
})
|
||||
})
|
||||
|
||||
it('generates a resized "web" video', function () {
|
||||
var o = output.paths('holidays/seagull.mp4', 'video', {})
|
||||
should(o.video).eql({
|
||||
path: 'media/large/holidays/seagull.mp4',
|
||||
rel: 'video:resized'
|
||||
})
|
||||
})
|
||||
|
||||
it('can point downloads to the large version', function () {
|
||||
var o = output.paths('holidays/seagull.mp4', 'video', {
|
||||
downloadVideos: 'large'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: 'media/large/holidays/seagull.mp4',
|
||||
rel: 'video:resized'
|
||||
})
|
||||
})
|
||||
|
||||
it('can point downloads to a copy in the output folder', function () {
|
||||
var o = output.paths('holidays/seagull.mp4', 'video', {
|
||||
downloadVideos: 'copy'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: 'media/original/holidays/seagull.mp4',
|
||||
rel: 'fs:copy'
|
||||
})
|
||||
})
|
||||
|
||||
it('can point downloads to a symlink to the originals', function () {
|
||||
var o = output.paths('holidays/seagull.mp4', 'video', {
|
||||
downloadVideos: 'symlink'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: 'media/original/holidays/seagull.mp4',
|
||||
rel: 'fs:symlink'
|
||||
})
|
||||
})
|
||||
|
||||
it('can point downloads to an existing link', function () {
|
||||
var o = output.paths('holidays/seagull.mp4', 'video', {
|
||||
downloadVideos: 'link',
|
||||
downloadLinkPrefix: '../myphotos'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: '../myphotos/holidays/seagull.mp4',
|
||||
rel: 'fs:link'
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Download links', function () {
|
||||
it('can use a relative link prefix', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {
|
||||
downloadPhotos: 'link',
|
||||
downloadLinkPrefix: '../myphotos'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: '../myphotos/holidays/beach.jpg',
|
||||
rel: 'fs:link'
|
||||
})
|
||||
})
|
||||
|
||||
it('can use a relative link prefix ending with a slash', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {
|
||||
downloadPhotos: 'link',
|
||||
downloadLinkPrefix: '../myphotos/'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: '../myphotos/holidays/beach.jpg',
|
||||
rel: 'fs:link'
|
||||
})
|
||||
})
|
||||
|
||||
it('can use an absolute link prefix', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {
|
||||
downloadPhotos: 'link',
|
||||
downloadLinkPrefix: '/Photos'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: '/Photos/holidays/beach.jpg',
|
||||
rel: 'fs:link'
|
||||
})
|
||||
})
|
||||
|
||||
it('can use an absolute link prefix ending with a slash', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {
|
||||
downloadPhotos: 'link',
|
||||
downloadLinkPrefix: '/Photos/'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: '/Photos/holidays/beach.jpg',
|
||||
rel: 'fs:link'
|
||||
})
|
||||
})
|
||||
|
||||
it('can use a URL prefix', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {
|
||||
downloadPhotos: 'link',
|
||||
downloadLinkPrefix: 'http://mygallery.com/photos'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: 'http://mygallery.com/photos/holidays/beach.jpg',
|
||||
rel: 'fs:link'
|
||||
})
|
||||
})
|
||||
|
||||
it('can use a URL prefix ending with a slash', function () {
|
||||
var o = output.paths('holidays/beach.jpg', 'image', {
|
||||
downloadPhotos: 'link',
|
||||
downloadLinkPrefix: 'http://mygallery.com/photos/'
|
||||
})
|
||||
should(o.download).eql({
|
||||
path: 'http://mygallery.com/photos/holidays/beach.jpg',
|
||||
rel: 'fs:link'
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user