2017-12-07 13:04:16 +00:00
|
|
|
const messages = require('./messages')
|
|
|
|
const path = require('path')
|
|
|
|
const yargs = require('yargs')
|
2018-04-12 08:53:15 +00:00
|
|
|
const os = require('os')
|
2019-07-07 20:09:20 +00:00
|
|
|
const _ = require('lodash')
|
2017-12-07 13:04:16 +00:00
|
|
|
|
|
|
|
const OPTIONS = {
|
|
|
|
|
|
|
|
// ------------------------------------
|
|
|
|
// Required arguments
|
|
|
|
// ------------------------------------
|
|
|
|
|
|
|
|
'input': {
|
|
|
|
group: 'Required:',
|
|
|
|
description: 'Path to the folder with all photos/videos',
|
2019-07-07 20:09:20 +00:00
|
|
|
type: 'string',
|
2017-12-07 13:04:16 +00:00
|
|
|
normalize: true,
|
|
|
|
demand: true
|
|
|
|
},
|
|
|
|
'output': {
|
|
|
|
group: 'Required:',
|
|
|
|
description: 'Output path for the static website',
|
2019-07-07 20:09:20 +00:00
|
|
|
type: 'string',
|
2017-12-07 13:04:16 +00:00
|
|
|
normalize: true,
|
|
|
|
demand: true
|
|
|
|
},
|
|
|
|
|
2019-01-08 20:45:02 +00:00
|
|
|
// ------------------------------------
|
|
|
|
// Input options
|
|
|
|
// ------------------------------------
|
|
|
|
'include-photos': {
|
|
|
|
group: 'Input options:',
|
|
|
|
description: 'Include photos in the gallery',
|
|
|
|
type: 'boolean',
|
|
|
|
'default': true
|
|
|
|
},
|
|
|
|
'include-videos': {
|
|
|
|
group: 'Input options:',
|
|
|
|
description: 'Include videos in the gallery',
|
|
|
|
type: 'boolean',
|
|
|
|
'default': true
|
|
|
|
},
|
|
|
|
'include-raw-photos': {
|
|
|
|
group: 'Input options:',
|
|
|
|
description: 'Include raw photos in the gallery',
|
|
|
|
type: 'boolean',
|
|
|
|
'default': false
|
|
|
|
},
|
2019-01-23 21:48:54 +00:00
|
|
|
'include': {
|
|
|
|
group: 'Input options:',
|
|
|
|
description: 'Glob pattern of files to include',
|
2019-01-23 21:52:30 +00:00
|
|
|
type: 'array'
|
2019-01-23 21:48:54 +00:00
|
|
|
},
|
|
|
|
'exclude': {
|
|
|
|
group: 'Input options:',
|
|
|
|
description: 'Glob pattern of files to exclude',
|
2019-01-23 21:52:30 +00:00
|
|
|
type: 'array'
|
2019-01-23 21:48:54 +00:00
|
|
|
},
|
2019-01-08 20:45:02 +00:00
|
|
|
|
2017-12-07 13:04:16 +00:00
|
|
|
// ------------------------------------
|
|
|
|
// Output options
|
|
|
|
// ------------------------------------
|
|
|
|
|
|
|
|
'thumb-size': {
|
|
|
|
group: 'Output options:',
|
|
|
|
description: 'Pixel size of the square thumbnails',
|
|
|
|
type: 'number',
|
|
|
|
'default': 120
|
|
|
|
},
|
|
|
|
'large-size': {
|
|
|
|
group: 'Output options:',
|
|
|
|
description: 'Pixel height of the fullscreen photos',
|
|
|
|
type: 'number',
|
|
|
|
'default': 1000
|
|
|
|
},
|
2018-05-09 17:59:00 +00:00
|
|
|
'photo-quality': {
|
|
|
|
group: 'Output options:',
|
|
|
|
description: 'Quality of the resized/converted photos',
|
|
|
|
type: 'number',
|
|
|
|
'default': 90
|
|
|
|
},
|
2019-01-07 20:48:44 +00:00
|
|
|
'video-quality': {
|
|
|
|
group: 'Output options:',
|
|
|
|
description: 'Quality of the converted video (percent)',
|
|
|
|
type: 'number',
|
|
|
|
'default': 75
|
|
|
|
},
|
|
|
|
'video-bitrate': {
|
|
|
|
group: 'Output options:',
|
|
|
|
description: 'Bitrate of the converted videos (e.g. 120k)',
|
|
|
|
type: 'string',
|
|
|
|
'default': null
|
|
|
|
},
|
|
|
|
'video-format': {
|
|
|
|
group: 'Output options:',
|
|
|
|
description: 'Video output format',
|
|
|
|
choices: ['mp4', 'webm'],
|
|
|
|
'default': 'mp4'
|
|
|
|
},
|
2019-02-07 21:08:38 +00:00
|
|
|
'photo-preview': {
|
2017-12-07 13:04:16 +00:00
|
|
|
group: 'Output options:',
|
2019-02-07 21:08:38 +00:00
|
|
|
description: 'How lightbox photos are generated',
|
|
|
|
choices: ['resize', 'copy', 'symlink', 'link'],
|
|
|
|
'default': 'resize'
|
2017-12-07 13:04:16 +00:00
|
|
|
},
|
2019-02-07 21:08:38 +00:00
|
|
|
'video-preview': {
|
2017-12-07 13:04:16 +00:00
|
|
|
group: 'Output options:',
|
2019-02-07 21:08:38 +00:00
|
|
|
description: 'How lightbox videos are generated',
|
|
|
|
choices: ['resize', 'copy', 'symlink', 'link'],
|
|
|
|
'default': 'resize'
|
2017-12-07 13:04:16 +00:00
|
|
|
},
|
2019-02-07 21:08:38 +00:00
|
|
|
'photo-download': {
|
2017-12-07 13:04:16 +00:00
|
|
|
group: 'Output options:',
|
2019-02-07 21:08:38 +00:00
|
|
|
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',
|
2017-12-07 13:04:16 +00:00
|
|
|
type: 'string'
|
|
|
|
},
|
|
|
|
'cleanup': {
|
|
|
|
group: 'Output options:',
|
|
|
|
description: 'Remove any output file that\'s no longer needed',
|
|
|
|
type: 'boolean',
|
|
|
|
'default': false
|
|
|
|
},
|
2018-05-09 18:01:55 +00:00
|
|
|
'concurrency': {
|
2018-05-14 20:05:33 +00:00
|
|
|
group: 'Output options:',
|
2018-05-09 18:01:55 +00:00
|
|
|
description: 'Number of parallel parsing/processing operations',
|
|
|
|
type: 'number',
|
|
|
|
'default': os.cpus().length
|
|
|
|
},
|
2019-02-13 21:18:54 +00:00
|
|
|
'output-structure': {
|
|
|
|
group: 'Output options:',
|
|
|
|
description: 'File and folder structure for output media',
|
|
|
|
choices: ['folders', 'suffix'],
|
|
|
|
'default': 'folders'
|
|
|
|
},
|
2018-05-14 20:05:33 +00:00
|
|
|
'gm-args': {
|
|
|
|
group: 'Output options:',
|
|
|
|
description: 'Custom image processing arguments for GraphicsMagick',
|
|
|
|
type: 'array'
|
|
|
|
},
|
2018-05-15 18:28:57 +00:00
|
|
|
'watermark': {
|
|
|
|
group: 'Output options:',
|
|
|
|
description: 'Path to a transparent PNG to be overlaid on all images',
|
2019-07-07 20:09:20 +00:00
|
|
|
type: 'string',
|
|
|
|
normalize: true
|
2018-05-15 18:28:57 +00:00
|
|
|
},
|
|
|
|
'watermark-position': {
|
|
|
|
group: 'Output options:',
|
|
|
|
description: 'Position of the watermark',
|
|
|
|
choices: [
|
|
|
|
'Repeat', 'Center', 'NorthWest', 'North', 'NorthEast',
|
|
|
|
'West', 'East', 'SouthWest', 'South', 'SouthEast'
|
|
|
|
]
|
|
|
|
},
|
2017-12-07 13:04:16 +00:00
|
|
|
|
|
|
|
// ------------------------------------
|
|
|
|
// Album options
|
|
|
|
// ------------------------------------
|
|
|
|
|
|
|
|
'albums-from': {
|
|
|
|
group: 'Album options:',
|
2017-12-23 09:32:10 +00:00
|
|
|
description: 'How files are grouped into albums',
|
|
|
|
type: 'array',
|
|
|
|
'default': ['%path']
|
2017-12-07 13:04:16 +00:00
|
|
|
},
|
|
|
|
'sort-albums-by': {
|
|
|
|
group: 'Album options:',
|
|
|
|
description: 'How to sort albums',
|
|
|
|
choices: ['title', 'start-date', 'end-date'],
|
|
|
|
'default': 'start-date'
|
|
|
|
},
|
|
|
|
'sort-albums-direction': {
|
|
|
|
group: 'Album options:',
|
|
|
|
description: 'Album sorting direction',
|
|
|
|
choices: ['asc', 'desc'],
|
|
|
|
'default': 'asc'
|
|
|
|
},
|
|
|
|
'sort-media-by': {
|
|
|
|
group: 'Album options:',
|
|
|
|
description: 'How to sort photos and videos',
|
|
|
|
choices: ['filename', 'date'],
|
|
|
|
'default': 'date'
|
|
|
|
},
|
|
|
|
'sort-media-direction': {
|
|
|
|
group: 'Album options:',
|
|
|
|
description: 'Media sorting direction',
|
|
|
|
choices: ['asc', 'desc'],
|
|
|
|
'default': 'asc'
|
|
|
|
},
|
2019-07-07 17:38:32 +00:00
|
|
|
'home-album-name': {
|
|
|
|
group: 'Album options:',
|
|
|
|
description: 'Name of the top-level album',
|
|
|
|
type: 'string',
|
|
|
|
'default': 'Home'
|
|
|
|
},
|
2019-03-17 21:56:48 +00:00
|
|
|
'album-zip-files': {
|
|
|
|
group: 'Album options:',
|
|
|
|
description: 'Create a ZIP file per album',
|
|
|
|
type: 'boolean',
|
|
|
|
'default': false
|
|
|
|
},
|
2017-12-07 13:04:16 +00:00
|
|
|
|
|
|
|
// ------------------------------------
|
|
|
|
// Website options
|
|
|
|
// ------------------------------------
|
|
|
|
|
|
|
|
'index': {
|
|
|
|
group: 'Website options:',
|
|
|
|
description: 'Filename of the home page',
|
2019-07-07 20:09:20 +00:00
|
|
|
type: 'string',
|
2017-12-07 13:04:16 +00:00
|
|
|
'default': 'index.html'
|
|
|
|
},
|
|
|
|
'albums-output-folder': {
|
|
|
|
group: 'Website options:',
|
|
|
|
description: 'Output subfolder for HTML albums (default: website root)',
|
2019-07-07 20:09:20 +00:00
|
|
|
type: 'string',
|
2017-12-07 13:04:16 +00:00
|
|
|
'default': '.'
|
|
|
|
},
|
|
|
|
'theme': {
|
|
|
|
group: 'Website options:',
|
2018-06-03 07:18:10 +00:00
|
|
|
description: 'Name of a built-in gallery theme',
|
2019-03-31 21:08:35 +00:00
|
|
|
choices: ['classic', 'cards', 'mosaic', 'flow'],
|
2017-12-07 13:04:16 +00:00
|
|
|
'default': 'classic'
|
|
|
|
},
|
2018-06-03 07:18:10 +00:00
|
|
|
'theme-path': {
|
|
|
|
group: 'Website options:',
|
|
|
|
description: 'Path to a custom theme',
|
2019-07-07 20:09:20 +00:00
|
|
|
type: 'string',
|
2018-06-03 07:18:10 +00:00
|
|
|
normalize: true
|
|
|
|
},
|
2018-05-15 18:32:42 +00:00
|
|
|
'theme-style': {
|
|
|
|
group: 'Website options:',
|
|
|
|
description: 'Path to a custom LESS/CSS file for additional styles',
|
2019-07-07 20:09:20 +00:00
|
|
|
type: 'string',
|
2018-05-15 18:32:42 +00:00
|
|
|
normalize: true
|
|
|
|
},
|
2019-06-05 20:45:02 +00:00
|
|
|
'theme-settings': {
|
|
|
|
group: 'Website options:',
|
|
|
|
description: 'Path to a JSON file with theme settings',
|
2019-07-07 20:09:20 +00:00
|
|
|
type: 'string',
|
2019-06-05 20:45:02 +00:00
|
|
|
normalize: true
|
|
|
|
},
|
2017-12-07 13:04:16 +00:00
|
|
|
'title': {
|
|
|
|
group: 'Website options:',
|
|
|
|
description: 'Website title',
|
2019-07-07 20:09:20 +00:00
|
|
|
type: 'string',
|
2017-12-07 13:04:16 +00:00
|
|
|
'default': 'Photo album'
|
|
|
|
},
|
|
|
|
'footer': {
|
|
|
|
group: 'Website options:',
|
|
|
|
description: 'Text or HTML footer',
|
2019-07-07 20:09:20 +00:00
|
|
|
type: 'string',
|
2017-12-07 13:04:16 +00:00
|
|
|
'default': null
|
|
|
|
},
|
|
|
|
'google-analytics': {
|
|
|
|
group: 'Website options:',
|
|
|
|
description: 'Code for Google Analytics tracking',
|
|
|
|
type: 'string'
|
|
|
|
},
|
2018-10-18 05:55:46 +00:00
|
|
|
'embed-exif': {
|
|
|
|
group: 'Website options:',
|
|
|
|
description: 'Embed the exif metadata for each image into the gallery page',
|
|
|
|
type: 'boolean',
|
|
|
|
'default': false
|
|
|
|
},
|
2017-12-07 13:04:16 +00:00
|
|
|
|
|
|
|
// ------------------------------------
|
|
|
|
// Misc options
|
|
|
|
// ------------------------------------
|
|
|
|
|
|
|
|
'config': {
|
2019-01-08 20:45:43 +00:00
|
|
|
group: 'Misc options:',
|
2017-12-07 13:04:16 +00:00
|
|
|
description: 'JSON config file (one key per argument)',
|
|
|
|
normalize: true
|
|
|
|
},
|
|
|
|
|
2017-12-07 13:06:35 +00:00
|
|
|
'log': {
|
2019-01-08 20:45:43 +00:00
|
|
|
group: 'Misc options:',
|
2017-12-07 13:06:35 +00:00
|
|
|
description: 'Print a detailed text log',
|
2019-06-13 20:36:31 +00:00
|
|
|
choices: ['default', 'info', 'debug', 'trace'],
|
|
|
|
'default': 'default'
|
2017-12-07 13:06:35 +00:00
|
|
|
},
|
|
|
|
|
2017-12-11 10:56:51 +00:00
|
|
|
'usage-stats': {
|
2019-01-08 20:45:43 +00:00
|
|
|
group: 'Misc options:',
|
2017-12-11 10:56:51 +00:00
|
|
|
description: 'Enable anonymous usage statistics',
|
2017-12-07 13:04:16 +00:00
|
|
|
type: 'boolean',
|
|
|
|
'default': true
|
|
|
|
},
|
|
|
|
|
2017-12-23 10:28:14 +00:00
|
|
|
'dry-run': {
|
2019-01-08 20:45:43 +00:00
|
|
|
group: 'Misc options:',
|
2017-12-23 10:28:14 +00:00
|
|
|
description: "Update the index, but don't create the media files / website",
|
|
|
|
type: 'boolean',
|
|
|
|
'default': false
|
|
|
|
},
|
|
|
|
|
2017-12-07 13:04:16 +00:00
|
|
|
// ------------------------------------
|
|
|
|
// Deprecated options
|
|
|
|
// ------------------------------------
|
|
|
|
|
|
|
|
'original-photos': {
|
|
|
|
group: 'Deprecated:',
|
|
|
|
description: 'Copy and allow download of full-size photos',
|
2019-02-07 21:08:38 +00:00
|
|
|
type: 'boolean'
|
2017-12-07 13:04:16 +00:00
|
|
|
},
|
|
|
|
'original-videos': {
|
|
|
|
group: 'Deprecated:',
|
|
|
|
description: 'Copy and allow download of full-size videos',
|
2019-02-07 21:08:38 +00:00
|
|
|
type: 'boolean'
|
2017-12-23 09:32:10 +00:00
|
|
|
},
|
|
|
|
'albums-date-format': {
|
2018-05-14 20:09:40 +00:00
|
|
|
group: 'Deprecated:',
|
2019-02-07 21:30:45 +00:00
|
|
|
description: 'How albums are named in <date> mode [moment.js pattern]'
|
2018-05-15 18:32:42 +00:00
|
|
|
},
|
|
|
|
'css': {
|
|
|
|
group: 'Deprecated:',
|
|
|
|
description: 'Path to a custom provided CSS/LESS file for styling',
|
|
|
|
normalize: true
|
2019-02-07 21:08:38 +00:00
|
|
|
},
|
|
|
|
'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'
|
2017-12-07 13:04:16 +00:00
|
|
|
}
|
2018-05-09 18:01:55 +00:00
|
|
|
|
2017-12-07 13:04:16 +00:00
|
|
|
}
|
|
|
|
|
2018-04-24 19:19:33 +00:00
|
|
|
// explicitly pass <process.argv> so we can unit test this logic
|
2017-12-22 11:28:37 +00:00
|
|
|
// otherwise it pre-loads all process arguments on require()
|
|
|
|
exports.get = (args) => {
|
2019-07-07 20:09:20 +00:00
|
|
|
const parsedOptions = yargs(args)
|
2017-12-07 13:04:16 +00:00
|
|
|
.usage(messages.USAGE())
|
|
|
|
.wrap(null)
|
|
|
|
.help('help')
|
|
|
|
.config('config')
|
|
|
|
.options(OPTIONS)
|
|
|
|
.epilogue(messages.CONFIG_USAGE())
|
|
|
|
.argv
|
|
|
|
|
2019-02-07 21:30:45 +00:00
|
|
|
// Warn users when they use deprecated options
|
|
|
|
const deprecated = Object.keys(OPTIONS).filter(name => OPTIONS[name].group === 'Deprecated:')
|
2019-07-07 20:09:20 +00:00
|
|
|
const specified = deprecated.filter(name => typeof parsedOptions[name] !== 'undefined')
|
2019-02-07 21:30:45 +00:00
|
|
|
if (specified.length > 0) {
|
|
|
|
const warnings = specified.map(name => `Warning: --${name} is deprecated`)
|
|
|
|
console.error(warnings.join('\n') + '\n')
|
|
|
|
}
|
|
|
|
|
2019-07-07 20:09:20 +00:00
|
|
|
// Delete all options containing dashes, because yargs already aliases them as camelCase
|
|
|
|
// This means we can process the camelCase version only after that
|
|
|
|
const opts = _.omitBy(parsedOptions, (value, key) => key.indexOf('-') >= 0)
|
|
|
|
|
2017-12-07 13:04:16 +00:00
|
|
|
// Make input/output folder absolute paths
|
2019-07-07 20:09:20 +00:00
|
|
|
opts.input = path.resolve(opts.input)
|
|
|
|
opts.output = path.resolve(opts.output)
|
2017-12-07 13:04:16 +00:00
|
|
|
|
|
|
|
// By default, use relative links to the input folder
|
2019-07-07 20:09:20 +00:00
|
|
|
if (opts.downloadLinkPrefix) opts.linkPrefix = opts.downloadLinkPrefix
|
|
|
|
if (!opts.linkPrefix) {
|
|
|
|
opts.linkPrefix = path.relative(opts.output, opts.input)
|
2017-12-07 13:04:16 +00:00
|
|
|
}
|
|
|
|
|
2018-05-15 18:32:42 +00:00
|
|
|
// Convert deprecated --download
|
2019-07-07 20:09:20 +00:00
|
|
|
if (opts.originalPhotos) opts.downloadPhotos = 'copy'
|
|
|
|
if (opts.originalVideos) opts.downloadVideos = 'copy'
|
|
|
|
if (opts.downloadPhotos) opts.photoDownload = opts.downloadPhotos
|
|
|
|
if (opts.downloadVideos) opts.videoDownload = opts.downloadVideos
|
|
|
|
if (opts.photoDownload === 'large') opts.photoDownload = 'resize'
|
|
|
|
if (opts.videoDownload === 'large') opts.videoDownload = 'resize'
|
2017-12-07 13:04:16 +00:00
|
|
|
|
2018-05-15 18:32:42 +00:00
|
|
|
// Convert deprecated --albums-from
|
2019-07-07 20:09:20 +00:00
|
|
|
replaceInArray(opts.albumsFrom, 'folders', '%path')
|
|
|
|
replaceInArray(opts.albumsFrom, 'date', `{${opts.albumsDateFormat}}`)
|
2017-12-22 21:37:08 +00:00
|
|
|
|
2018-05-15 18:32:42 +00:00
|
|
|
// Convert deprecated --css
|
2019-07-07 20:09:20 +00:00
|
|
|
if (opts.css) opts.themeStyle = opts.css
|
2018-05-15 18:32:42 +00:00
|
|
|
|
2018-05-14 20:05:33 +00:00
|
|
|
// Add a dash prefix to any --gm-args value
|
|
|
|
// We can't specify the prefix on the CLI otherwise the parser thinks it's a thumbsup arg
|
2019-07-07 20:09:20 +00:00
|
|
|
if (opts.gmArgs) {
|
|
|
|
opts.gmArgs = opts.gmArgs.map(val => `-${val}`)
|
2018-05-14 20:05:33 +00:00
|
|
|
}
|
|
|
|
|
2019-07-07 20:09:20 +00:00
|
|
|
return opts
|
2017-12-07 13:04:16 +00:00
|
|
|
}
|
2017-12-22 21:37:08 +00:00
|
|
|
|
|
|
|
function replaceInArray (list, match, replacement) {
|
|
|
|
for (var i = 0; i < list.length; ++i) {
|
|
|
|
if (list[i] === match) {
|
|
|
|
list[i] = replacement
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|