feat(resize): new options to control preview images (resize, copy, symlink…)

Fixes #115
pull/143/head
Romain 5 years ago
parent 014a44cfe8
commit 96bb3ad902

@ -95,20 +95,22 @@ Input options:
--exclude Glob pattern of files to exclude [array]
Output options:
--thumb-size Pixel size of the square thumbnails [number] [default: 120]
--large-size Pixel height of the fullscreen photos [number] [default: 1000]
--photo-quality Quality of the resized/converted photos [number] [default: 90]
--video-quality Quality of the converted video (percent) [number] [default: 75]
--video-bitrate Bitrate of the converted videos (e.g. 120k) [string] [default: null]
--video-format Video output format [choices: "mp4", "webm"] [default: "mp4"]
--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]
--concurrency Number of parallel parsing/processing operations [number] [default: 4]
--gm-args Custom image processing arguments for GraphicsMagick [array]
--watermark Path to a transparent PNG to be overlaid on all images [string]
--watermark-position Position of the watermark [choices: "Repeat", "Center", "NorthWest", "North", "NorthEast", "West", "East", "SouthWest", "South", "SouthEast"]
--thumb-size Pixel size of the square thumbnails [number] [default: 120]
--large-size Pixel height of the fullscreen photos [number] [default: 1000]
--photo-quality Quality of the resized/converted photos [number] [default: 90]
--video-quality Quality of the converted video (percent) [number] [default: 75]
--video-bitrate Bitrate of the converted videos (e.g. 120k) [string] [default: null]
--video-format Video output format [choices: "mp4", "webm"] [default: "mp4"]
--photo-preview How lightbox photos are generated [choices: "resize", "copy", "symlink", "link"] [default: "resize"]
--video-preview How lightbox videos are generated [choices: "resize", "copy", "symlink", "link"] [default: "resize"]
--photo-download How downloadable photos are generated [choices: "resize", "copy", "symlink", "link"] [default: "resize"]
--video-download How downloadable videos are generated [choices: "resize", "copy", "symlink", "link"] [default: "resize"]
--link-prefix Path or URL prefix for "linked" photos and videos [string]
--cleanup Remove any output file that's no longer needed [boolean] [default: false]
--concurrency Number of parallel parsing/processing operations [number] [default: 4]
--gm-args Custom image processing arguments for GraphicsMagick [array]
--watermark Path to a transparent PNG to be overlaid on all images [string]
--watermark-position Position of the watermark [choices: "Repeat", "Center", "NorthWest", "North", "NorthEast", "West", "East", "SouthWest", "South", "SouthEast"]
Album options:
--albums-from How files are grouped into albums [array] [default: ["%path"]]
@ -135,10 +137,13 @@ Misc options:
--dry-run Update the index, but don't create the media files / website [boolean] [default: false]
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]
--albums-date-format How albums are named in <date> mode [moment.js pattern] [default: "YYYY-MM"]
--css Path to a custom provided CSS/LESS file for styling [string]
--original-photos Copy and allow download of full-size photos [boolean]
--original-videos Copy and allow download of full-size videos [boolean]
--albums-date-format How albums are named in <date> mode [moment.js pattern] [default: "YYYY-MM"]
--css Path to a custom provided CSS/LESS file for styling [string]
--download-photos Target of the photo download links [choices: "large", "copy", "symlink", "link"]
--download-videos Target of the video download links [choices: "large", "copy", "symlink", "link"]
--download-link-prefix Path or URL prefix for linked downloads [string]
Options:
--version Show version number [boolean]

@ -94,21 +94,33 @@ const OPTIONS = {
choices: ['mp4', 'webm'],
'default': 'mp4'
},
'download-photos': {
'photo-preview': {
group: 'Output options:',
description: 'Target of the photo download links',
choices: ['large', 'copy', 'symlink', 'link'],
'default': 'large'
description: 'How lightbox photos are generated',
choices: ['resize', 'copy', 'symlink', 'link'],
'default': 'resize'
},
'download-videos': {
'video-preview': {
group: 'Output options:',
description: 'Target of the video download links',
choices: ['large', 'copy', 'symlink', 'link'],
'default': 'large'
description: 'How lightbox videos are generated',
choices: ['resize', 'copy', 'symlink', 'link'],
'default': 'resize'
},
'download-link-prefix': {
'photo-download': {
group: 'Output options:',
description: 'Path or URL prefix for linked downloads',
description: 'How downloadable photos are generated',
choices: ['resize', 'copy', 'symlink', 'link'],
'default': 'resize'
},
'video-download': {
group: 'Output options:',
description: 'How downloadable videos are generated',
choices: ['resize', 'copy', 'symlink', 'link'],
'default': 'resize'
},
'link-prefix': {
group: 'Output options:',
description: 'Path or URL prefix for "linked" photos and videos',
type: 'string'
},
'cleanup': {
@ -267,14 +279,12 @@ const OPTIONS = {
'original-photos': {
group: 'Deprecated:',
description: 'Copy and allow download of full-size photos',
type: 'boolean',
'default': false
type: 'boolean'
},
'original-videos': {
group: 'Deprecated:',
description: 'Copy and allow download of full-size videos',
type: 'boolean',
'default': false
type: 'boolean'
},
'albums-date-format': {
group: 'Deprecated:',
@ -285,6 +295,21 @@ const OPTIONS = {
group: 'Deprecated:',
description: 'Path to a custom provided CSS/LESS file for styling',
normalize: true
},
'download-photos': {
group: 'Deprecated:',
description: 'Target of the photo download links',
choices: ['large', 'copy', 'symlink', 'link']
},
'download-videos': {
group: 'Deprecated:',
description: 'Target of the video download links',
choices: ['large', 'copy', 'symlink', 'link']
},
'download-link-prefix': {
group: 'Deprecated:',
description: 'Path or URL prefix for linked downloads',
type: 'string'
}
}
@ -306,13 +331,18 @@ exports.get = (args) => {
opts['output'] = path.resolve(opts['output'])
// By default, use relative links to the input folder
if (!opts['download-link-prefix']) {
opts['download-link-prefix'] = path.relative(opts['output'], opts['input'])
if (opts['download-link-prefix']) opts['link-prefix'] = opts['download-link-prefix']
if (!opts['link-prefix']) {
opts['link-prefix'] = path.relative(opts['output'], opts['input'])
}
// Convert deprecated --download
if (opts['original-photos']) opts['download-photos'] = 'copy'
if (opts['original-videos']) opts['download-videos'] = 'copy'
if (opts['download-photos']) opts['photo-download'] = opts['download-photos']
if (opts['download-videos']) opts['video-download'] = opts['download-videos']
if (opts['photo-download'] === 'large') opts['photo-download'] = 'resize'
if (opts['video-download'] === 'large') opts['video-download'] = 'resize'
// Convert deprecated --albums-from
replaceInArray(opts['albums-from'], 'folders', '%path')
@ -344,9 +374,11 @@ exports.get = (args) => {
videoQuality: opts['video-quality'],
videoBitrate: opts['video-bitrate'],
videoFormat: opts['video-format'],
downloadPhotos: opts['download-photos'],
downloadVideos: opts['download-videos'],
downloadLinkPrefix: opts['download-link-prefix'],
photoPreview: opts['photo-preview'],
videoPreview: opts['video-preview'],
photoDownload: opts['photo-download'],
videoDownload: opts['video-download'],
linkPrefix: opts['link-prefix'],
albumsFrom: opts['albums-from'],
albumsDateFormat: opts['albums-date-format'],
sortAlbumsBy: opts['sort-albums-by'],

@ -6,76 +6,69 @@ const BROWSER_SUPPORTED_EXT = /\.(jpg|jpeg|png|gif)$/i
exports.paths = function (filepath, mediaType, opts) {
if (mediaType === 'image') {
const items = imageOutput(filepath)
items.download = download(filepath, opts['downloadPhotos'], opts['downloadLinkPrefix'], items.large)
return items
return image(filepath, opts)
} else if (mediaType === 'video') {
const items = videoOutput(filepath, opts['videoFormat'])
items.download = download(filepath, opts['downloadVideos'], opts['downloadLinkPrefix'], items.video)
return items
return video(filepath, opts)
} else {
warn(`Unsupported file type <${mediaType}> for ${filepath}`)
return {}
}
}
function imageOutput (filepath) {
const extension = path.extname(filepath)
if (!extension.match(BROWSER_SUPPORTED_EXT)) {
filepath = ext(filepath, 'jpg')
function image (filepath, opts) {
return {
thumbnail: relationship(filepath, 'photo:thumbnail'),
large: relationship(filepath, shortRel('image', opts.photoPreview), opts),
download: relationship(filepath, shortRel('image', opts.photoDownload), opts)
}
}
function video (filepath, opts) {
return {
thumbnail: {
path: 'media/thumbs/' + filepath,
rel: 'photo:thumbnail'
},
large: {
path: 'media/large/' + filepath,
rel: 'photo:large'
}
thumbnail: relationship(filepath, 'video:thumbnail'),
large: relationship(filepath, 'video:poster'),
video: relationship(filepath, shortRel('video', opts.videoPreview), opts),
download: relationship(filepath, shortRel('video', opts.videoDownload), opts)
}
}
function shortRel (mediaType, shorthand) {
shorthand = shorthand || 'resize'
switch (shorthand) {
case 'resize': return mediaType === 'image' ? 'photo:large' : 'video:resized'
case 'copy': return 'fs:copy'
case 'symlink': return 'fs:symlink'
case 'link': return 'fs:link'
default: return null
}
}
function videoOutput (filepath, videoFormat) {
function relationship (filepath, rel, options) {
return {
thumbnail: {
path: 'media/thumbs/' + ext(filepath, 'jpg'),
rel: 'video:thumbnail'
},
large: {
path: 'media/large/' + ext(filepath, 'jpg'),
rel: 'video:poster'
},
video: {
path: 'media/large/' + ext(filepath, videoFormat),
rel: 'video:resized'
}
path: pathForRelationship(filepath, rel, options),
rel: rel
}
}
function download (filepath, downloadConfig, linkPrefix, largeVersion) {
switch (downloadConfig) {
case 'copy':
return {
path: path.join('media', 'original', filepath),
rel: 'fs:copy'
}
case 'symlink':
return {
path: path.join('media', 'original', filepath),
rel: 'fs:symlink'
}
case 'link':
return {
path: join(linkPrefix, filepath),
rel: 'fs:link'
}
case 'large':
default:
return largeVersion
function pathForRelationship (filepath, rel, options) {
switch (rel) {
case 'photo:thumbnail': return 'media/thumbs/' + supportedPhotoFilename(filepath)
case 'photo:large': return 'media/large/' + supportedPhotoFilename(filepath)
case 'video:thumbnail': return 'media/thumbs/' + ext(filepath, 'jpg')
case 'video:poster': return 'media/large/' + ext(filepath, 'jpg')
case 'video:resized': return 'media/large/' + ext(filepath, options.videoFormat)
case 'fs:copy': return path.join('media', 'original', filepath)
case 'fs:symlink': return path.join('media', 'original', filepath)
case 'fs:link': return join(options.linkPrefix, filepath)
default: return null
}
}
function supportedPhotoFilename (filepath) {
const extension = path.extname(filepath)
return extension.match(BROWSER_SUPPORTED_EXT) ? filepath : ext(filepath, 'jpg')
}
function ext (file, ext) {
return file.replace(/\.[a-z0-9]+$/i, '.' + ext)
}

@ -53,22 +53,47 @@ describe('options', function () {
it('--original-photos false', () => {
const args = BASE_ARGS.concat(['--original-photos false'])
const opts = options.get(args)
should(opts.downloadPhotos).eql('large')
should(opts.photoDownload).eql('resize')
})
it('--original-photos true', () => {
const args = BASE_ARGS.concat(['--original-photos'])
const opts = options.get(args)
should(opts.downloadPhotos).eql('copy')
should(opts.photoDownload).eql('copy')
})
it('--original-videos false', () => {
const args = BASE_ARGS.concat(['--original-videos false'])
const opts = options.get(args)
should(opts.downloadVideos).eql('large')
should(opts.videoDownload).eql('resize')
})
it('--original-videos true', () => {
const args = BASE_ARGS.concat(['--original-videos'])
const opts = options.get(args)
should(opts.downloadVideos).eql('copy')
should(opts.videoDownload).eql('copy')
})
it('--download-photos copy', () => {
const args = BASE_ARGS.concat(['--download-photos', 'copy'])
const opts = options.get(args)
should(opts.photoDownload).eql('copy')
})
it('--download-videos copy', () => {
const args = BASE_ARGS.concat(['--download-videos', 'copy'])
const opts = options.get(args)
should(opts.videoDownload).eql('copy')
})
it('--download-photos large', () => {
const args = BASE_ARGS.concat(['--download-photos', 'large'])
const opts = options.get(args)
should(opts.photoDownload).eql('resize')
})
it('--download-videos large', () => {
const args = BASE_ARGS.concat(['--download-videos', 'large'])
const opts = options.get(args)
should(opts.videoDownload).eql('resize')
})
it('--download-link-prefix url', () => {
const args = BASE_ARGS.concat(['--download-link-prefix', 'url'])
const opts = options.get(args)
should(opts.linkPrefix).eql('url')
})
it('--albums-from folders', () => {
const args = BASE_ARGS.concat(['--albums-from', 'folders'])

@ -21,7 +21,7 @@ describe('Output paths', function () {
it('can point downloads to the large version', function () {
const o = output.paths('holidays/beach.jpg', 'image', {
downloadPhotos: 'large'
photoDownload: 'resize'
})
should(o.download).eql({
path: 'media/large/holidays/beach.jpg',
@ -29,9 +29,19 @@ describe('Output paths', function () {
})
})
it('can point previews to a copy in the output folder', function () {
const o = output.paths('holidays/beach.jpg', 'image', {
photoPreview: 'copy'
})
should(o.large).eql({
path: 'media/original/holidays/beach.jpg',
rel: 'fs:copy'
})
})
it('can point downloads to a copy in the output folder', function () {
const o = output.paths('holidays/beach.jpg', 'image', {
downloadPhotos: 'copy'
photoDownload: 'copy'
})
should(o.download).eql({
path: 'media/original/holidays/beach.jpg',
@ -41,7 +51,7 @@ describe('Output paths', function () {
it('can point downloads to a symlink to the originals', function () {
const o = output.paths('holidays/beach.jpg', 'image', {
downloadPhotos: 'symlink'
photoDownload: 'symlink'
})
should(o.download).eql({
path: 'media/original/holidays/beach.jpg',
@ -51,8 +61,8 @@ describe('Output paths', function () {
it('can point downloads to an existing link', function () {
const o = output.paths('holidays/beach.jpg', 'image', {
downloadPhotos: 'link',
downloadLinkPrefix: '../myphotos'
photoDownload: 'link',
linkPrefix: '../myphotos'
})
should(o.download).eql({
path: '../myphotos/holidays/beach.jpg',
@ -103,7 +113,7 @@ describe('Output paths', function () {
it('can point downloads to the large version', function () {
const o = output.paths('holidays/seagull.mp4', 'video', {
downloadVideos: 'large',
videoDownload: 'resize',
videoFormat: 'mp4'
})
should(o.download).eql({
@ -114,7 +124,7 @@ describe('Output paths', function () {
it('can point downloads to a copy in the output folder', function () {
const o = output.paths('holidays/seagull.mp4', 'video', {
downloadVideos: 'copy'
videoDownload: 'copy'
})
should(o.download).eql({
path: 'media/original/holidays/seagull.mp4',
@ -122,9 +132,19 @@ describe('Output paths', function () {
})
})
it('can point previews to a copy in the output folder', function () {
const o = output.paths('holidays/seagull.mp4', 'video', {
videoPreview: 'copy'
})
should(o.video).eql({
path: 'media/original/holidays/seagull.mp4',
rel: 'fs:copy'
})
})
it('can point downloads to a symlink to the originals', function () {
const o = output.paths('holidays/seagull.mp4', 'video', {
downloadVideos: 'symlink'
videoDownload: 'symlink'
})
should(o.download).eql({
path: 'media/original/holidays/seagull.mp4',
@ -134,8 +154,8 @@ describe('Output paths', function () {
it('can point downloads to an existing link', function () {
const o = output.paths('holidays/seagull.mp4', 'video', {
downloadVideos: 'link',
downloadLinkPrefix: '../myphotos'
videoDownload: 'link',
linkPrefix: '../myphotos'
})
should(o.download).eql({
path: '../myphotos/holidays/seagull.mp4',
@ -147,8 +167,8 @@ describe('Output paths', function () {
describe('Download links', function () {
it('can use a relative link prefix', function () {
const o = output.paths('holidays/beach.jpg', 'image', {
downloadPhotos: 'link',
downloadLinkPrefix: '../myphotos'
photoDownload: 'link',
linkPrefix: '../myphotos'
})
should(o.download).eql({
path: '../myphotos/holidays/beach.jpg',
@ -158,8 +178,8 @@ describe('Output paths', function () {
it('can use a relative link prefix ending with a slash', function () {
const o = output.paths('holidays/beach.jpg', 'image', {
downloadPhotos: 'link',
downloadLinkPrefix: '../myphotos/'
photoDownload: 'link',
linkPrefix: '../myphotos/'
})
should(o.download).eql({
path: '../myphotos/holidays/beach.jpg',
@ -169,8 +189,8 @@ describe('Output paths', function () {
it('can use an absolute link prefix', function () {
const o = output.paths('holidays/beach.jpg', 'image', {
downloadPhotos: 'link',
downloadLinkPrefix: '/Photos'
photoDownload: 'link',
linkPrefix: '/Photos'
})
should(o.download).eql({
path: '/Photos/holidays/beach.jpg',
@ -180,8 +200,8 @@ describe('Output paths', function () {
it('can use an absolute link prefix ending with a slash', function () {
const o = output.paths('holidays/beach.jpg', 'image', {
downloadPhotos: 'link',
downloadLinkPrefix: '/Photos/'
photoDownload: 'link',
linkPrefix: '/Photos/'
})
should(o.download).eql({
path: '/Photos/holidays/beach.jpg',
@ -191,8 +211,8 @@ describe('Output paths', function () {
it('can use a URL prefix', function () {
const o = output.paths('holidays/beach.jpg', 'image', {
downloadPhotos: 'link',
downloadLinkPrefix: 'http://mygallery.com/photos'
photoDownload: 'link',
linkPrefix: 'http://mygallery.com/photos'
})
should(o.download).eql({
path: 'http://mygallery.com/photos/holidays/beach.jpg',
@ -202,8 +222,8 @@ describe('Output paths', function () {
it('can use a URL prefix ending with a slash', function () {
const o = output.paths('holidays/beach.jpg', 'image', {
downloadPhotos: 'link',
downloadLinkPrefix: 'http://mygallery.com/photos/'
photoDownload: 'link',
linkPrefix: 'http://mygallery.com/photos/'
})
should(o.download).eql({
path: 'http://mygallery.com/photos/holidays/beach.jpg',

Loading…
Cancel
Save