diff --git a/app/back-end/author.js b/app/back-end/author.js index ed042d44..c24d4263 100644 --- a/app/back-end/author.js +++ b/app/back-end/author.js @@ -292,7 +292,7 @@ class Author extends Model { featuredImage = path.parse(this.additionalData.featuredImage).base; } - // If post is cancelled - get the previous featured image + // If author is cancelled - get the previous featured image if (cancelEvent && this.id !== 0) { let featuredImageSqlQuery = `SELECT additional_data FROM authors WHERE id = @id`; @@ -313,6 +313,12 @@ class Author extends Model { authorDir = 'temp'; } + let imagesInAuthorViewSettings = []; + + if (this.additionalData && this.additionalData.viewConfig) { + imagesInAuthorViewSettings = Object.values(this.additionalData.viewConfig).filter(item => item.type === "image").map(item => item.value); + } + // Iterate through images for (let i in images) { let imagePath = images[i]; @@ -323,7 +329,14 @@ class Author extends Model { continue; } - if ((cancelEvent && authorDir === 'temp') || featuredImage !== imagePath) { + // Remove files which does not exist as featured image and authorViewSettings + if( + (cancelEvent && authorDir === 'temp') || + ( + imagesInAuthorViewSettings.indexOf(imagePath) === -1 && + featuredImage !== imagePath + ) + ) { try { fs.unlinkSync(fullPath); } catch(e) { diff --git a/app/back-end/builddata.json b/app/back-end/builddata.json index ff0e326d..3ac98af2 100644 --- a/app/back-end/builddata.json +++ b/app/back-end/builddata.json @@ -1,4 +1,4 @@ { "version": "0.45.2", - "build": 16609 -} + "build": 16629 +} \ No newline at end of file diff --git a/app/back-end/image.js b/app/back-end/image.js index 6a8032e4..a5b65c95 100644 --- a/app/back-end/image.js +++ b/app/back-end/image.js @@ -23,6 +23,8 @@ class Image extends Model { if (imageData.id === 'website') { this.id = 'website'; + } else if (imageData.id === 'defaults') { + this.id = 'defaults'; } // App instance @@ -95,7 +97,16 @@ class Image extends Model { let galleryDirPath = ''; let responsiveDirPath = ''; - if (this.imageType === 'pluginImages') { + if (this.id === 'defaults' && this.imageType === 'contentImages') { + dirPath = path.join(this.siteDir, 'input', 'media', 'posts', 'defaults'); + responsiveDirPath = path.join(this.siteDir, 'input', 'media', 'posts', 'defaults', 'responsive'); + } else if (this.id === 'defaults' && this.imageType === 'tagImages') { + dirPath = path.join(this.siteDir, 'input', 'media', 'tags', 'defaults'); + responsiveDirPath = path.join(this.siteDir, 'input', 'media', 'tags', 'defaults', 'responsive'); + } else if (this.id === 'defaults' && this.imageType === 'authorImages') { + dirPath = path.join(this.siteDir, 'input', 'media', 'authors', 'defaults'); + responsiveDirPath = path.join(this.siteDir, 'input', 'media', 'authors', 'defaults', 'responsive'); + } else if (this.imageType === 'pluginImages') { dirPath = path.join(this.siteDir, 'input', 'media', 'plugins', this.pluginDir); } else if (this.id === 'website') { dirPath = path.join(this.siteDir, 'input', 'media', 'website'); diff --git a/app/back-end/modules/render-html/helpers/diffCopy.js b/app/back-end/modules/render-html/helpers/diffCopy.js index 04bc550e..4745375a 100644 --- a/app/back-end/modules/render-html/helpers/diffCopy.js +++ b/app/back-end/modules/render-html/helpers/diffCopy.js @@ -117,7 +117,7 @@ class DiffCopy { postIDs = postIDs.map(id => (id).toString()); for (let i = 0; i < allPostFolders.length; i++) { - if (allPostFolders[i] === '.' || allPostFolders[i] === '..') { + if (allPostFolders[i] === '.' || allPostFolders[i] === '..' || allPostFolders[i] === 'defaults') { continue; } diff --git a/app/back-end/modules/render-html/helpers/files.js b/app/back-end/modules/render-html/helpers/files.js index dd361777..9890afee 100644 --- a/app/back-end/modules/render-html/helpers/files.js +++ b/app/back-end/modules/render-html/helpers/files.js @@ -167,7 +167,7 @@ class Files { static async copyMediaFiles (inputDir, outputDir, postIDs) { let basePathInput = path.join(inputDir, 'media'); let basePathOutput = path.join(outputDir, 'media'); - let dirs = ['website', 'files', 'tags', 'authors']; + let dirs = ['website', 'files', 'tags', 'authors', 'posts/defaults']; if (postIDs[0] === 0) { postIDs[0] = 'temp'; diff --git a/app/back-end/modules/render-html/helpers/view-settings.js b/app/back-end/modules/render-html/helpers/view-settings.js index 7c4e6b28..e17acc9b 100644 --- a/app/back-end/modules/render-html/helpers/view-settings.js +++ b/app/back-end/modules/render-html/helpers/view-settings.js @@ -1,5 +1,7 @@ +const sizeOf = require('image-size'); + class ViewSettings { - static override(viewSettings, defaultViewConfig) { + static override(viewSettings, defaultViewConfig, itemData, rendererInstance) { let outputConfig = {}; // Generate default settings structure @@ -31,6 +33,36 @@ class ViewSettings { outputConfig[defaultViewFields[i]] = defaultField; } } + } else if (typeof field !== 'undefined' && field.type === 'image') { + let dirName = 'posts'; + + if (itemData.type === 'tag') { + dirName = 'tags'; + } else if (itemData.type === 'author') { + dirName = 'authors'; + } + + let imageDimensions = false; + let imagePath = '/media/' + dirName + '/defaults/' + defaultField; + + if (defaultField) { + try { + imageDimensions = sizeOf(rendererInstance.inputDir + imagePath); + } catch(e) { + imageDimensions = { + height: false, + width: false + }; + } + + outputConfig[defaultViewFields[i]] = { + url: rendererInstance.siteConfig.domain + imagePath, + width: imageDimensions.width, + height: imageDimensions.height + }; + } else { + outputConfig[defaultViewFields[i]] = false; + } } else { if (defaultField === '0') { defaultField = 0; @@ -50,34 +82,64 @@ class ViewSettings { for(let i = 0; i < viewFields.length; i++) { let field = viewSettings[viewFields[i]]; - if(typeof field !== 'undefined' && field.value) { - if(field.value !== "") { - outputConfig[viewFields[i]] = field.value; + if (field.type === 'image') { + if (field.value) { + let dirName = 'posts'; + + if (itemData.type === 'tag') { + dirName = 'tags'; + } else if (itemData.type === 'author') { + dirName = 'authors'; + } + + let imageDimensions = false; + let imagePath = '/media/' + dirName + '/' + itemData.id + '/' + field.value; + + try { + imageDimensions = sizeOf(rendererInstance.inputDir + imagePath); + } catch(e) { + imageDimensions = { + height: false, + width: false + }; + } + + outputConfig[defaultViewFields[i]] = { + url: rendererInstance.siteConfig.domain + imagePath, + width: imageDimensions.width, + height: imageDimensions.height + }; + } + } else { + if(typeof field !== 'undefined' && field.value) { + if(field.value !== "") { + outputConfig[viewFields[i]] = field.value; + } + } else if(typeof field === 'string' && field !== "") { + outputConfig[viewFields[i]] = field; } - } else if(typeof field === 'string' && field !== "") { - outputConfig[viewFields[i]] = field; - } - if((field.type && field.type === 'select') || !field.type) { - if( - field === 0 || - field === '0' || - field.value === 0 || - field.value === '0' - ) { - outputConfig[viewFields[i]] = false; - } else if( - field === 1 || - field === '1' || - field.value === 1 || - field.value === '1' - ) { - outputConfig[viewFields[i]] = true; - } else { - if (typeof field.value !== 'undefined' && field.value !== '') { - outputConfig[viewFields[i]] = JSON.stringify(field.value).replace(/"/g, ''); - } else if (typeof field !== 'object' && field !== '') { - outputConfig[viewFields[i]] = JSON.stringify(field).replace(/"/g, ''); + if((field.type && field.type === 'select') || !field.type) { + if( + field === 0 || + field === '0' || + field.value === 0 || + field.value === '0' + ) { + outputConfig[viewFields[i]] = false; + } else if( + field === 1 || + field === '1' || + field.value === 1 || + field.value === '1' + ) { + outputConfig[viewFields[i]] = true; + } else { + if (typeof field.value !== 'undefined' && field.value !== '') { + outputConfig[viewFields[i]] = JSON.stringify(field.value).replace(/"/g, ''); + } else if (typeof field !== 'object' && field !== '') { + outputConfig[viewFields[i]] = JSON.stringify(field).replace(/"/g, ''); + } } } } diff --git a/app/back-end/modules/render-html/renderer-cache.js b/app/back-end/modules/render-html/renderer-cache.js index 9ea4c825..6a94943b 100644 --- a/app/back-end/modules/render-html/renderer-cache.js +++ b/app/back-end/modules/render-html/renderer-cache.js @@ -76,7 +76,10 @@ class RendererCache { let tagViewConfigObject = JSON.parse(JSON.stringify(this.themeConfig.tagConfig)); tags = tags.map(tag => { - let tagViewConfig = this.getViewSettings(tagViewConfigObject, tag); + let tagViewConfig = this.getViewSettings(tagViewConfigObject, tag, { + type: 'tag', + id: tag.id + }); let newTag = new Tag(tag, this.renderer, mainTagIDs); newTag.setTagViewConfig(tagViewConfig); return newTag; @@ -186,7 +189,10 @@ class RendererCache { let authorViewConfigObject = JSON.parse(JSON.stringify(this.themeConfig.authorConfig)); authors = authors.map(author => { - let authorViewConfig = this.getViewSettings(authorViewConfigObject, author); + let authorViewConfig = this.getViewSettings(authorViewConfigObject, author, { + type: 'author', + id: author.id + }); let newAuthor = new Author(author, this.renderer); newAuthor.setAuthorViewConfig(authorViewConfig); return newAuthor; @@ -397,7 +403,10 @@ class RendererCache { postViewSettings = JSON.parse(postViewData.value); } - return ViewSettingsHelper.override(postViewSettings, defaultPostViewConfig); + return ViewSettingsHelper.override(postViewSettings, defaultPostViewConfig, { + type: 'post', + id: postID + }, this.renderer); } /** @@ -408,7 +417,7 @@ class RendererCache { * * @returns {object} */ - getViewSettings(defaultViewConfig, itemData) { + getViewSettings(defaultViewConfig, itemData, itemConfig) { let viewSettings = {}; if (itemData && itemData.additional_data) { @@ -423,7 +432,7 @@ class RendererCache { } } - return ViewSettingsHelper.override(viewSettings, defaultViewConfig); + return ViewSettingsHelper.override(viewSettings, defaultViewConfig, itemConfig, this.renderer); } } diff --git a/app/back-end/modules/render-html/renderer.js b/app/back-end/modules/render-html/renderer.js index 98d62b0e..075e0f0f 100644 --- a/app/back-end/modules/render-html/renderer.js +++ b/app/back-end/modules/render-html/renderer.js @@ -298,7 +298,7 @@ class Renderer { await FilesHelper.copyAssetsFiles(this.themeDir, this.outputDir, this.themeConfig); FilesHelper.copyDynamicAssetsFiles(this.themeDir, this.outputDir, this.themeConfig); - FilesHelper.copyMediaFiles(this.inputDir, this.outputDir, [this.itemID]); + await FilesHelper.copyMediaFiles(this.inputDir, this.outputDir, [this.itemID]); FilesHelper.copyPluginFiles(this.inputDir, this.outputDir, this.pluginsDir); this.triggerEvent('afterRender'); @@ -313,7 +313,7 @@ class Renderer { let postIDs = Object.keys(this.cachedItems.posts); await FilesHelper.copyAssetsFiles(this.themeDir, this.outputDir, this.themeConfig); FilesHelper.copyDynamicAssetsFiles(this.themeDir, this.outputDir, this.themeConfig); - FilesHelper.copyMediaFiles(this.inputDir, this.outputDir, postIDs); + await FilesHelper.copyMediaFiles(this.inputDir, this.outputDir, postIDs); FilesHelper.copyPluginFiles(this.inputDir, this.outputDir, this.pluginsDir); this.triggerEvent('afterRender'); @@ -339,7 +339,7 @@ class Renderer { await FilesHelper.copyAssetsFiles(this.themeDir, this.outputDir, this.themeConfig); FilesHelper.copyDynamicAssetsFiles(this.themeDir, this.outputDir, this.themeConfig); - FilesHelper.copyMediaFiles(this.inputDir, this.outputDir, postIDsToRender); + await FilesHelper.copyMediaFiles(this.inputDir, this.outputDir, postIDsToRender); FilesHelper.copyPluginFiles(this.inputDir, this.outputDir, this.pluginsDir); this.triggerEvent('afterRender'); @@ -365,7 +365,7 @@ class Renderer { await FilesHelper.copyAssetsFiles(this.themeDir, this.outputDir, this.themeConfig); FilesHelper.copyDynamicAssetsFiles(this.themeDir, this.outputDir, this.themeConfig); - FilesHelper.copyMediaFiles(this.inputDir, this.outputDir, postIDsToRender); + await FilesHelper.copyMediaFiles(this.inputDir, this.outputDir, postIDsToRender); FilesHelper.copyPluginFiles(this.inputDir, this.outputDir, this.pluginsDir); this.triggerEvent('afterRender'); @@ -973,7 +973,10 @@ class Renderer { } } - return ViewSettingsHelper.override(postViewSettings, defaultPostViewConfig); + return ViewSettingsHelper.override(postViewSettings, defaultPostViewConfig, { + type: 'post', + id: postID + }); } /* diff --git a/app/back-end/post.js b/app/back-end/post.js index 78714469..f0f64325 100644 --- a/app/back-end/post.js +++ b/app/back-end/post.js @@ -631,6 +631,12 @@ class Post extends Model { postDir = 'temp'; } + let imagesInPostViewSettings = []; + + if (this.postViewSettings) { + imagesInPostViewSettings = Object.values(this.postViewSettings).filter(item => item.type === "image").map(item => item.value); + } + // Iterate through images for (let i in images) { let imagePath = images[i]; @@ -641,10 +647,14 @@ class Post extends Model { continue; } - // Remove files which does not exist in the post text + // Remove files which does not exist in the post text, as featured image and postViewSettings if( (cancelEvent && postDir === 'temp') || - (this.text.indexOf(imagePath) === -1 && featuredImage !== imagePath) + ( + this.text.indexOf(imagePath) === -1 && + imagesInPostViewSettings.indexOf(imagePath) === -1 && + featuredImage !== imagePath + ) ) { try { fs.unlinkSync(fullPath); diff --git a/app/back-end/tag.js b/app/back-end/tag.js index f5b86e86..1eba07b5 100644 --- a/app/back-end/tag.js +++ b/app/back-end/tag.js @@ -293,6 +293,12 @@ class Tag extends Model { tagDir = 'temp'; } + let imagesInTagViewSettings = []; + + if (this.additionalData && this.additionalData.viewConfig) { + imagesInTagViewSettings = Object.values(this.additionalData.viewConfig).filter(item => item.type === "image").map(item => item.value); + } + // Iterate through images for (let i in images) { let imagePath = images[i]; @@ -303,7 +309,14 @@ class Tag extends Model { continue; } - if ((cancelEvent && tagDir === 'temp') || featuredImage !== imagePath) { + // Remove files which does not exist as featured image and authorViewSettings + if( + (cancelEvent && tagDir === 'temp') || + ( + imagesInTagViewSettings.indexOf(imagePath) === -1 && + featuredImage !== imagePath + ) + ) { try { fs.unlinkSync(fullPath); } catch(e) { diff --git a/app/back-end/themes.js b/app/back-end/themes.js index c2eafa9b..7449ab55 100644 --- a/app/back-end/themes.js +++ b/app/back-end/themes.js @@ -521,6 +521,60 @@ class Themes { this.removeResponsiveImages(fullPath); } } + + // clean up unnecessary default images + let assetsToCheck = [ + { + dir: 'posts', + configType: 'postConfig' + }, + { + dir: 'tags', + configType: 'tagConfig' + }, + { + dir: 'authors', + configType: 'authorConfig' + } + ]; + + let configObject = JSON.parse(configString); + + for (let i = 0; i < assetsToCheck.length; i++) { + let dirToCheck = assetsToCheck[i].dir; + let configToCheck = assetsToCheck[i].configType; + let viewImagesDir = path.join(this.siteInputPath, 'media', dirToCheck, 'defaults'); + + if(!UtilsHelper.dirExists(viewImagesDir)) { + return; + } + + let viewImages = fs.readdirSync(viewImagesDir); + let configImages = Object.values(configObject[configToCheck]); + + // Iterate through images + for (let i in viewImages) { + let imagePath = viewImages[i]; + let fullPath = path.join(viewImagesDir, imagePath); + + // Skip dirs and symlinks + if (imagePath === '.' || imagePath === '..' || imagePath === 'responsive' || imagePath === 'gallery') { + continue; + } + + // Remove files which does not exist in the post text + if (configImages.indexOf(imagePath) === -1) { + try { + fs.unlinkSync(fullPath); + } catch(e) { + console.error(e); + } + + // Remove responsive images + this.removeResponsiveImages(fullPath); + } + } + } } /* diff --git a/app/src/components/AuthorForm.vue b/app/src/components/AuthorForm.vue index 4ad11cd9..d82cc983 100644 --- a/app/src/components/AuthorForm.vue +++ b/app/src/components/AuthorForm.vue @@ -341,6 +341,13 @@ :outputFormat="field.outputFormat ? field.outputFormat : 'RGBAorHEX'"> + + diff --git a/app/src/components/TagForm.vue b/app/src/components/TagForm.vue index d5ecab62..33f04192 100644 --- a/app/src/components/TagForm.vue +++ b/app/src/components/TagForm.vue @@ -311,6 +311,13 @@ :outputFormat="field.outputFormat ? field.outputFormat : 'RGBAorHEX'"> + + diff --git a/app/src/components/ThemeSettings.vue b/app/src/components/ThemeSettings.vue index 62a13ae9..cbd0c53f 100644 --- a/app/src/components/ThemeSettings.vue +++ b/app/src/components/ThemeSettings.vue @@ -335,6 +335,13 @@ :customCssClasses="field.customCssClasses"> + + + + + + + +