cleanup...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-12-17 18:59:29 +03:00
parent 9c72528908
commit c750895a4a

View File

@ -185,440 +185,9 @@ var SharpActions = actions.Actions({
// from filesystem.IndexFormat...
},
// XXX either make this a session task or make this survive loading
// a new index...
// XXX revise return values...
// XXX make backup name pattern configurable...
// XXX CROP ready for crop support...
_makeResizedImage: ['- Image/',
core.doc`Make resized image(s)...
.makeResizedImage(gid, size, path[, options])
.makeResizedImage(gids, size, path[, options])
-> promise
Image size formats:
500px - resize to make image's *largest* dimension 500 pixels (default).
500p - resize to make image's *smallest* dimension 500 pixels.
500 - same as 500px
options format:
{
// output image name / name pattern...
//
// NOTE: for multiple images this should be a pattern and not an
// explicit name...
// NOTE: if not given this defaults to: "%n"
name: null | <str>,
// image name pattern data...
//
// NOTE: for more info on pattern see: .formatImageName(..)
data: null | { .. },
// if true and image is smaller than size enlarge it...
//
// default: null / false
enlarge: null | true,
// overwrite, backup or skip (default) existing images...
//
// default: null / false
overwrite: null | true | 'backup',
// if true do not write an image if it's smaller than size...
//
// default: null / false
skipSmaller: null | true,
// XXX not implemented...
transform: ...,
crop: ...,
timestamp: ...,
logger: ...,
, }
NOTE: all options are optional.
NOTE: this will not overwrite existing images.
`,
core.sessionQueueHandler('Make resized image',
// get/normalize images...
// XXX if this is to be a global task (i.e. .queueHandler(..)) we'll
// need to get all the image data here...
// ...paths and orientation data...
function(queue, images, size, path, options){
// sanity check...
if(arguments.length < 4){
throw new Error('.makeResizedImage(..): '
+'need at least: images, size and path.') }
return [
(images == null || images == 'all') ?
this.data.getImages('all')
: images == 'current' ?
[this.current]
: images instanceof Array ?
images
: [images],
...[...arguments].slice(2),
]},
function(gid, size, path, options={}){
var that = this
// sizing...
var fit =
typeof(size) == typeof('str') ?
(size.endsWith('px') ?
'inside'
: size.endsWith('p') ?
'outside'
: 'inside')
: 'inside'
size = parseInt(size)
// options...
var {
// naming...
name,
data,
// file handling...
enlarge,
skipSmaller,
overwrite,
// transformations...
transform,
// XXX CROP not implemented...
//crop,
timestamp,
//logger,
} = options
// defaults...
name = name || '%n'
transform = transform === undefined ?
true
: transform
timestamp = timestamp || Date.timeStamp()
// backup...
// XXX make backup name pattern configurable...
var backupName = function(to){
var i = 0
while(fse.existsSync(`${to}.${timestamp}.bak`+ (i || ''))){
i++ }
return `${to}.${timestamp}.bak`+ (i || '') }
// skip non-images...
if(!['image', null, undefined]
.includes(this.images[gid].type)){
// XXX what should we return???
return Promise.resolve() }
// paths...
var source = this.getImagePath(gid)
var to = pathlib.resolve(
this.location.path,
pathlib.join(
path,
// if name is not a pattern do not re-format it...
name.includes('%') ?
this.formatImageName(name, gid, data || {})
: name))
var img = sharp(source)
return (skipSmaller ?
// skip if smaller than size...
img
.metadata()
.then(function(m){
// skip...
if((fit == 'inside'
&& Math.max(m.width, m.height) < size)
|| (fit == 'outside'
&& Math.min(m.width, m.height) < size)){
return }
// continue...
return img })
: Promise.resolve(img))
// prepare to write...
.then(function(img){
return img
&& ensureDir(pathlib.dirname(to))
.then(function(){
// handle existing image...
if(fse.existsSync(to)){
// rename...
if(overwrite == 'backup'){
fse.renameSync(to, backupName(to))
// remove...
} else if(overwrite){
fse.removeSync(to)
// skip...
} else {
return Promise.reject('target exists') } }
// write...
return img
.clone()
// handle transform (.orientation / .flip) and .crop...
.run(function(){
var img = that.images[gid]
if(transform && (img.orientation || img.flipped)){
img.orientation
&& this.rotate(img.orientation)
img.flipped
&& img.flipped.includes('horizontal')
&& this.flip() }
img.flipped
&& img.flipped.includes('vertical')
&& this.flop()
// XXX CROP
//if(crop){
// // XXX
//}
})
.resize({
width: size,
height: size,
fit: fit,
withoutEnlargement: !enlarge,
})
.withMetadata()
.toFile(to)
.then(function(){
// XXX what should we return???
return to }) }) }) })],
_makeResizedImage2: ['- Image/',
core.doc`Make resized image(s)...
.makeResizedImage(gid, size, path[, options])
.makeResizedImage(gids, size, path[, options])
-> promise
Image size formats:
500px - resize to make image's *largest* dimension 500 pixels (default).
500p - resize to make image's *smallest* dimension 500 pixels.
500 - same as 500px
options format:
{
// output image name / name pattern...
//
// NOTE: for multiple images this should be a pattern and not an
// explicit name...
// NOTE: if not given this defaults to: "%n"
name: null | <str>,
// image name pattern data...
//
// NOTE: for more info on pattern see: .formatImageName(..)
data: null | { .. },
// if true and image is smaller than size enlarge it...
//
// default: null / false
enlarge: null | true,
// overwrite, backup or skip (default) existing images...
//
// default: null / false
overwrite: null | true | 'backup',
// if true do not write an image if it's smaller than size...
//
// default: null / false
skipSmaller: null | true,
// XXX not implemented...
transform: ...,
crop: ...,
timestamp: ...,
logger: ...,
, }
NOTE: all options are optional.
NOTE: this will not overwrite existing images.
`,
core.queueHandler('Make resized image',
// queue the image data...
// NOTE: after this runs we should be completely independent
// of the current index...
// XXX for a very large number of images this can block for
// a substantial amount of time...
function(queue, images, size, path, options){
var that = this
// sanity check...
if(arguments.length < 4){
throw new Error('.makeResizedImage(..): '
+'need at least: images, size and path.') }
// options...
var {
name,
data,
} = options || {}
name = name || '%n'
// [source, to, image], ...args
return [
((images == null || images == 'all') ?
this.data.getimages('all')
: images == 'current' ?
[this.current]
: images instanceof array ?
images
: [images])
.map(function(gid){
var image = that.images[gid]
// skip non-images...
if(!image || !['image', null, undefined]
.includes(image.type)){
return [] }
return [[
// source...
that.getimagepath(gid),
// target...
pathlib.resolve(
that.location.path,
pathlib.join(
path,
// if name is not a pattern do not re-format it...
name.includes('%') ?
that.formatimagename(name, gid, data || {})
: name)),
// image data...
// note: we include only the stuff we need...
{
orientation: image.orientation,
flipped: image.flipped,
// crop...
},
]] })
.flat(),
...[...arguments].slice(2),
]},
function([source, to, image], size, _, options={}){
// sizing...
var fit =
typeof(size) == typeof('str') ?
(size.endsWith('px') ?
'inside'
: size.endsWith('p') ?
'outside'
: 'inside')
: 'inside'
size = parseInt(size)
// options...
var {
enlarge,
skipSmaller,
overwrite,
transform,
timestamp,
backupImagePattern,
//logger,
} = options
// defaults...
transform = transform === undefined ?
true
: transform
timestamp = timestamp || Date.timeStamp()
// backup by default...
overwrite = overwrite === undefined ?
'backup'
: overwrite
backupImagePattern =
(backupImagePattern
|| '${PATH}.${TIMESTAMP}${COUNT}.bak')
.replace(/\${PATH}|$PATH/, to)
.replace(/\${TIMESTAMP}|$TIMESTAMP/, timestamp)
// backup...
// NOTE: we are doing the check at the very last moment and
// not here to avoid race conditions as much as practical...
var backupName = function(){
var i = 0
var n
do{
n = backupImagePattern
.replace(/\${COUNT}|$COUNT/, i++ ? '.'+i : i)
} while(fse.existsSync(n))
return n }
var img = sharp(source)
return (skipSmaller ?
// skip if smaller than size...
img
.metadata()
.then(function(m){
// skip...
if((fit == 'inside'
&& Math.max(m.width, m.height) < size)
|| (fit == 'outside'
&& Math.min(m.width, m.height) < size)){
return }
// continue...
return img })
: Promise.resolve(img))
// prepare to write...
.then(function(img){
return img
&& ensureDir(pathlib.dirname(to))
.then(function(){
// handle existing image...
if(fse.existsSync(to)){
// rename...
if(overwrite == 'backup'){
fse.renameSync(to, backupName(to))
// remove...
} else if(overwrite){
fse.removeSync(to)
// skip...
} else {
return Promise.reject('target exists') } }
// write...
return img
.clone()
// handle transform (.orientation / .flip) and .crop...
.run(function(){
if(transform && (image.orientation || image.flipped)){
image.orientation
&& this.rotate(image.orientation)
image.flipped
&& image.flipped.includes('horizontal')
&& this.flip() }
image.flipped
&& image.flipped.includes('vertical')
&& this.flop()
// XXX CROP
//if(crop){
// // XXX
//}
})
.resize({
width: size,
height: size,
fit: fit,
withoutEnlargement: !enlarge,
})
.withMetadata()
.toFile(to)
.then(function(){
// XXX what should we return???
return to }) }) }) })],
// XXX we need to split this into two stages:
// - session queue handler
// - global queue handler
// i.e. call the second queue generator when the first one completes...
// or in other works chain queues -- essentially this is like
// calling .then(..) on a queue but doing it at definition...
makeResizedImage: ['- Image/',
core.doc`Make resized image(s)...