165 lines
5.8 KiB
TypeScript
165 lines
5.8 KiB
TypeScript
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'
|
|
import * as path from 'path'
|
|
import * as pMap from 'p-map'
|
|
import { resolve } from '@plastichub/osr-cli-commons/fs'
|
|
import { files } from '@plastichub/osr-cli-commons/glob'
|
|
|
|
import { sync as exists } from '@plastichub/fs/exists'
|
|
import { sync as read } from '@plastichub/fs/read'
|
|
|
|
import { logger as _logger } from '@plastichub/core/debug'
|
|
import * as ExifReader from 'exifreader'
|
|
|
|
import { translateText } from '@plastichub/osr-i18n/lib/translate'
|
|
import { resize, getResizePatterns, format, getFormats, meta } from '@plastichub/osr-media/lib/media/images'
|
|
|
|
import {
|
|
I18N_STORE,
|
|
|
|
OSR_ROOT, PRODUCT_CONFIG, PRODUCT_ROOT,
|
|
RETAIL_MEDIA_CACHE
|
|
} from './config'
|
|
import { GalleryImage } from './images'
|
|
|
|
const logger = _logger('ph-site')
|
|
const IMAGES_GLOB = '*.+(JPG|jpg|png|PNG|gif)'
|
|
|
|
export const productGallery = async (grunt, assetPath, product, lang, dstLanguage): Promise<GalleryImage[]> => {
|
|
product = '' + product
|
|
const root = resolve(PRODUCT_ROOT())
|
|
const productConfig: any = read(PRODUCT_CONFIG(product), "json")
|
|
if (!productConfig) {
|
|
logger.error('Product config not found !' + product)
|
|
return
|
|
}
|
|
const mediaPath = `${root}/${product}/${assetPath}/`
|
|
if (!exists(mediaPath)) {
|
|
return []
|
|
}
|
|
|
|
const galleryFiles = files(mediaPath, IMAGES_GLOB, {
|
|
cwd: mediaPath,
|
|
absolute: false
|
|
})
|
|
|
|
if (!galleryFiles) {
|
|
return
|
|
}
|
|
const removeBufferValues = (obj: any): any => {
|
|
for (const key in obj) {
|
|
const val = obj[key]
|
|
if (Buffer.isBuffer(val)) {
|
|
}
|
|
if (Buffer.isBuffer(val)) {
|
|
delete obj[key];
|
|
} else if (typeof val === 'object') {
|
|
removeBufferValues(val);
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
const removeArrayValues = (obj: any): any => {
|
|
for (const key in obj) {
|
|
if (key == 'id') {
|
|
delete obj[key]
|
|
}
|
|
if (Array.isArray(obj[key]) || Buffer.isBuffer(obj[key])) {
|
|
delete obj[key];
|
|
} else if (typeof obj[key] === 'object') {
|
|
removeArrayValues(obj[key]);
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
const removeEmptyObjects = (obj: any): any => {
|
|
for (const key in obj) {
|
|
if (typeof obj[key] === 'object' ||
|
|
(key == 'value' && typeof obj[key] === 'number' && obj[key] === 0 ||
|
|
key == 'base64')
|
|
) {
|
|
obj[key] = removeEmptyObjects(obj[key]);
|
|
if (Object.keys(obj[key]).length === 0) {
|
|
delete obj[key];
|
|
}
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
const removeArrays = (obj: any): any => {
|
|
for (const key in obj) {
|
|
if (key == 'description' && typeof obj[key] === 'string' && obj[key].split(',').length > 2) {
|
|
try {
|
|
if (Buffer.isBuffer(Buffer.from(obj[key].split(','))))
|
|
delete obj[key]
|
|
} catch (e) {
|
|
|
|
}
|
|
} else if (typeof obj[key] === 'object') {
|
|
removeArrays(obj[key]);
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
return await pMap(galleryFiles, async (file: string) => {
|
|
const parts = path.parse(file)
|
|
const filePath = path.join(mediaPath, file)
|
|
let imageMeta: any = await meta(filePath)
|
|
const exifRaw: any = await ExifReader.load(filePath)
|
|
const title = exifRaw?.title?.description || ''
|
|
const keywords = exifRaw?.['LastKeywordXMP']?.description || exifRaw?.iptc?.Keywords?.description || ''
|
|
const exifDescription = exifRaw?.['ImageDescription']?.description || ''
|
|
const width = exifRaw?.['Image Width']?.value
|
|
const height = exifRaw?.['Image Height']?.value
|
|
const lon = exifRaw?.['GPSLongitude']?.description
|
|
const lat = exifRaw?.['GPSLatitude']?.description
|
|
const description = exifDescription || exifRaw?.iptc?.['Caption/Abstract'].description || ''
|
|
imageMeta.exif = exifRaw
|
|
imageMeta = removeBufferValues(imageMeta)
|
|
imageMeta = removeArrayValues(imageMeta)
|
|
imageMeta = removeArrays(imageMeta)
|
|
imageMeta = removeEmptyObjects(imageMeta)
|
|
delete imageMeta.xmp
|
|
delete imageMeta.icc
|
|
delete imageMeta.exif.icc
|
|
delete imageMeta.exif.xmp
|
|
delete imageMeta.exif.iptc
|
|
const keywordsTranslated = await translateText(keywords || '', lang, dstLanguage,{
|
|
store: I18N_STORE(OSR_ROOT(), dstLanguage)
|
|
})
|
|
const assetUrl = (filePath) => `[[OSR_MACHINES_ASSETS_URL]]/[[product_relative]]/${assetPath}/${filePath}`
|
|
const ret: GalleryImage =
|
|
{
|
|
name: path.parse(file).name,
|
|
url: assetUrl(file),
|
|
thumb: assetUrl(`/20/webp/${parts.name}.webp`),
|
|
responsive: assetUrl(`/webp/${parts.name}.webp`),
|
|
meta: imageMeta || "",
|
|
keywords: keywords.split(',').map((k) => k.trim()),
|
|
description,
|
|
alt: `${description} - ${keywordsTranslated || ''}`,
|
|
width,
|
|
height,
|
|
title
|
|
}
|
|
return ret
|
|
})
|
|
}
|
|
export const compileProductAssets = async (grunt, product_root, srcLang, dstLanguage) => {
|
|
logger.info('Resize Product Media Assets ', product_root);
|
|
|
|
await resize(getResizePatterns(product_root, 'drawings'))
|
|
await format(getFormats(product_root, 'drawings'), { png: false, cache: RETAIL_MEDIA_CACHE })
|
|
|
|
await resize(getResizePatterns(product_root, 'renderings'))
|
|
await format(getFormats(product_root, 'renderings'), { png: false, cache: RETAIL_MEDIA_CACHE })
|
|
|
|
await resize(getResizePatterns(product_root, 'renderings/20'))
|
|
await format(getFormats(product_root, 'renderings/20'), { png: false, cache: RETAIL_MEDIA_CACHE })
|
|
|
|
await resize(getResizePatterns(product_root, 'media/gallery'))
|
|
await format(getFormats(product_root, 'media/gallery'), { png: false, cache: RETAIL_MEDIA_CACHE })
|
|
await resize(getResizePatterns(product_root, 'media/gallery/20'))
|
|
await format(getFormats(product_root, 'media/gallery/20'), { png: false, cache: RETAIL_MEDIA_CACHE })
|
|
}
|