Skip to content

Commit

Permalink
Merge branch 'v.0.46.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
dziudek committed Oct 31, 2024
2 parents 5b195b8 + ea5a587 commit 0047d42
Show file tree
Hide file tree
Showing 96 changed files with 910 additions and 408 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
[Publii](https://getpublii.com/) is a desktop-based CMS for Windows, Mac and Linux that makes creating static websites fast
and hassle-free, even for beginners.

**Current version: 0.46.1 (build 16918)**
**Current version: 0.46.2 (build 16966)**

## Why Publii?
Unlike static-site generators that are often unwieldy and difficult to use, Publii provides an
Expand Down
31 changes: 15 additions & 16 deletions app/back-end/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -358,17 +358,9 @@ class App {
this.currentLanguageMomentLocale = languageConfig.momentLocale;
this.currentWysiwygTranslation = languagesLoader.loadWysiwygTranslation(this.appConfig.language, this.appConfig.languageType);
}

if (
!this.currentLanguageTranslations ||
!languageConfig ||
(!this.currentWysiwygTranslation && this.currentLanguageName !== 'en-gb')
) {
this.loadDefaultLanguage(languagesLoader, true);
}
} else {
this.loadDefaultLanguage(languagesLoader, false);
}

this.loadDefaultLanguage(languagesLoader, false);
}

// Load plugins
Expand All @@ -380,15 +372,15 @@ class App {

// Load default language
loadDefaultLanguage (languagesLoader, errorOccurred = false) {
this.currentLanguageName = 'en-gb';
this.currentLanguageType = 'default';
this.currentLanguageTranslations = languagesLoader.loadTranslations('en-gb', 'default');
this.defaultLanguageName = 'en-gb';
this.defaultLanguageType = 'default';
this.defaultLanguageTranslations = languagesLoader.loadTranslations('en-gb', 'default');
let languageConfig = languagesLoader.loadLanguageConfig('en-gb', 'default');
this.currentLanguageMomentLocale = languageConfig.momentLocale;
this.currentWysiwygTranslation = languagesLoader.loadWysiwygTranslation('en-gb', 'default');
this.defaultLanguageMomentLocale = languageConfig.momentLocale;
this.defaultWysiwygTranslation = languagesLoader.loadWysiwygTranslation('en-gb', 'default');

if (errorOccurred) {
this.languageLoadingError = true;
this.defaultLanguageLoadingError = true;
}
}

Expand Down Expand Up @@ -665,6 +657,13 @@ class App {
momentLocale: self.currentLanguageMomentLocale,
languageLoadingError: self.languageLoadingError
},
defaultLanguage: {
name: self.defaultLanguageName,
translations: self.defaultLanguageTranslations,
wysiwygTranslation: self.defaultWysiwygTranslation,
momentLocale: self.defaultLanguageMomentLocale,
languageLoadingError: self.languageLoadingError
},
languages: self.languages,
languagesPath: self.languagesPath,
languagesDefaultPath: self.languagesDefaultPath,
Expand Down
6 changes: 4 additions & 2 deletions app/back-end/author.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,16 @@ class Author extends Model {
if (!this.isAuthorNameUnique()) {
return {
status: false,
message: 'author-duplicate-name'
message: 'author-duplicate-name',
authors: this.authorsData.load()
};
}

if (!this.isAuthorUsernameUnique()) {
return {
status: false,
message: 'author-duplicate-username'
message: 'author-duplicate-username',
authors: this.authorsData.load()
};
}

Expand Down
4 changes: 2 additions & 2 deletions app/back-end/builddata.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"version": "0.46.1",
"build": 16918
"version": "0.46.2",
"build": 16966
}
35 changes: 34 additions & 1 deletion app/back-end/events/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ class PageEvents {
let pagesFile = path.join(this.app.sitesDir, siteName, 'input', 'config', 'pages.config.json');

if (fs.existsSync(pagesFile)) {
event.sender.send('app-pages-hierarchy-loaded', JSON.parse(fs.readFileSync(pagesFile, { encoding: 'utf8' })));
let pagesHierarchy = JSON.parse(fs.readFileSync(pagesFile, { encoding: 'utf8' }));
pagesHierarchy = this.removeDuplicatedDataFromHierarchy(pagesHierarchy);
event.sender.send('app-pages-hierarchy-loaded', pagesHierarchy);
} else {
event.sender.send('app-pages-hierarchy-loaded', null);
}
Expand All @@ -95,8 +97,26 @@ class PageEvents {
ipcMain.on('app-pages-hierarchy-save', (event, pagesData) => {
let pagesFile = path.join(this.app.sitesDir, pagesData.siteName, 'input', 'config', 'pages.config.json');
pagesData.hierarchy = this.removeNullDataFromHierarchy(pagesData.hierarchy);
pagesData.hierarchy = this.removeDuplicatedDataFromHierarchy(pagesData.hierarchy);
fs.writeFileSync(pagesFile, JSON.stringify(pagesData.hierarchy, null, 4), { encoding: 'utf8' });
});

// Update pages hierarchy during post conversion
ipcMain.on('app-pages-hierarchy-update', (event, postIDs) => {
let pagesFile = path.join(this.app.sitesDir, pagesData.siteName, 'input', 'config', 'pages.config.json');
let pagesHierarchy = JSON.parse(fs.readFileSync(pagesFile, { encoding: 'utf8' }));

for (let i = 0; i < postIDs.length; i++) {
pagesHierarchy.push({
id: postIDs[i],
subpages: []
});
}

pagesHierarchy = this.removeNullDataFromHierarchy(pagesHierarchy);
pagesHierarchy = this.removeDuplicatedDataFromHierarchy(pagesHierarchy);
fs.writeFileSync(pagesFile, JSON.stringify(updatedHierarchy, null, 4), { encoding: 'utf8' });
});
}

removeNullDataFromHierarchy (data) {
Expand All @@ -107,6 +127,19 @@ class PageEvents {
subpages: item.subpages ? this.removeNullDataFromHierarchy(item.subpages) : []
}));
}

removeDuplicatedDataFromHierarchy (data) {
let existingIds = new Set();

return data.filter(item => {
if (existingIds.has(item.id)) {
return false;
}

existingIds.add(item.id);
return true;
});
}
}

module.exports = PageEvents;
10 changes: 5 additions & 5 deletions app/back-end/modules/import/wxr-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,15 @@ class WxrParser {
this.autop = autop;
this.postTypes = postTypes;

if(authors === 'wp-authors') {
this.importAuthors = true;
}

console.log('(i) CONFIG:');
console.log('- Import authors: ' + this.importAuthors);
console.log('- Used taxonomy: ' + this.usedTaxonomy);
console.log('- Use autop: '+ this.autop + "\n\n");
console.log('- Post types: '+ this.postTypes.toString() + "\n\n");

if(authors === 'wp-authors') {
this.importAuthors = true;
}
}

/**
Expand Down Expand Up @@ -720,7 +720,7 @@ class WxrParser {
let image = nextImg.imgUrl;
let imageFileName = url.parse(image);

if(imageFileName && imageFileName.pathname) {
if(imageFileName && imageFileName.pathname && imageFileName.protocol) {
imageFileName = path.basename(imageFileName.pathname);

download.image({
Expand Down
8 changes: 7 additions & 1 deletion app/back-end/modules/render-html/contexts/feed.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class RendererContextFeed extends RendererContext {
${featuredPostsCondition}
status NOT LIKE '%hidden%' AND
status NOT LIKE '%is-page%' AND
status NOT LIKE '%trashed%'
status NOT LIKE '%trashed%' AND
status NOT LIKE '%excluded_homepage%'
ORDER BY
created_at DESC
LIMIT
Expand Down Expand Up @@ -134,6 +135,11 @@ class RendererContextFeed extends RendererContext {
pt.tag_id = t.id
WHERE
pt.post_id = @postID
AND (
(json_valid(t.additional_data) AND json_extract(t.additional_data, '$.isHidden') = false)
OR t.additional_data IS NULL
OR t.additional_data = ''
)
ORDER BY
name DESC
`).all({
Expand Down
9 changes: 9 additions & 0 deletions app/back-end/modules/render-html/contexts/home.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ class RendererContextHome extends RendererContext {
this.metaTitle = this.siteConfig.advanced.metaTitle.replace(/%sitename/g, siteName);
this.metaDescription = this.siteConfig.advanced.metaDescription.replace(/%sitename/g, siteName);

if (
!this.siteConfig.advanced.usePageAsFrontpage &&
this.siteConfig.advanced.urls.postsPrefix &&
this.renderer.menuContext.indexOf('frontpage') > -1
) {
this.metaTitle = this.siteConfig.advanced.homepageMetaTitle.replace(/%sitename/g, siteName);
this.metaDescription = this.siteConfig.advanced.homepageMetaDescription.replace(/%sitename/g, siteName);
}

this.tags = this.renderer.commonData.tags.filter(tag => tag.additionalData.isHidden !== true);
this.mainTags = this.renderer.commonData.mainTags.filter(maintag => maintag.additionalData.isHidden !== true);
this.menus = this.renderer.commonData.menus;
Expand Down
2 changes: 1 addition & 1 deletion app/back-end/modules/render-html/handlebars/helpers/is.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* {{#is 'tag,post'}}
*
* Available phrases: index, tag, post, page, author, 404, search, pagination, index-pagination, tag-pagination, author-pagination
* Available phrases: index, blogindex, tag, post, page, author, 404, search, pagination, index-pagination, tag-pagination, author-pagination
*
* @returns {callback}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ function jsonLDHelper(rendererInstance, Handlebars) {
"@id": itemData.url,
};
jsonLDObject['headline'] = itemData.title;
jsonLDObject['datePublished'] = moment(itemData.createdAt).format('YYYY-MM-DDTHH:mm');
jsonLDObject['dateModified'] = moment(itemData.modifiedAt).format('YYYY-MM-DDTHH:mm');
jsonLDObject['datePublished'] = moment(itemData.createdAt).format('YYYY-MM-DDTHH:mmZ');
jsonLDObject['dateModified'] = moment(itemData.modifiedAt).format('YYYY-MM-DDTHH:mmZ');

if (itemData.featuredImage.url || context.data.website.logo) {
let imageUrl = '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ function menuItemClassesHelper(rendererInstance, Handlebars) {
if (hasActiveChild(this.items, context)) {
output.push(activeParentClass);
} else if (
(this.type === 'blogpage' && context[0] === 'blogpage') ||
(this.type === 'frontpage' && context[0] === 'frontpage') ||
(this.type === 'frontpage' && context[0] === 'page' && context[2] && context[2] === 'page-' + rendererInstance.siteConfig.advanced.pageAsFrontpage) ||
(this.type === 'tags' && context[0] === 'tags') ||
(this.type === context[0] && this.link === context[1])
) {
Expand Down
44 changes: 28 additions & 16 deletions app/back-end/modules/render-html/handlebars/helpers/menu-url.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,30 +51,42 @@ function menuURLHelper(rendererInstance, Handlebars) {
let parentItems = rendererInstance.cachedItems.pagesStructureHierarchy[this.linkID];
let pageSlug = this.link;

if (rendererInstance.siteConfig.advanced.urls.cleanUrls && parentItems && parentItems.length) {
let slugs = [];
if (rendererInstance.siteConfig.advanced.usePageAsFrontpage && rendererInstance.siteConfig.advanced.pageAsFrontpage === this.linkID) {
output = baseUrl + '/';

for (let i = 0; i < parentItems.length; i++) {
if (rendererInstance.cachedItems.pages[parentItems[i]]) {
slugs.push(rendererInstance.cachedItems.pages[parentItems[i]].slug);
}
}

slugs.push(this.link);
pageSlug = slugs.join('/');
}

if (rendererInstance.siteConfig.advanced.urls.cleanUrls) {
output = baseUrl + '/' + pageSlug + '/';
// In the preview mode we have to load URLs with
// index.html as filesystem on OS doesn't behave
// as the server environment and not redirect to
// a proper URL
if (rendererInstance.previewMode || rendererInstance.siteConfig.advanced.urls.addIndex) {
output += 'index.html';
}
}
} else {
output = baseUrl + '/' + pageSlug + '.html';
if (rendererInstance.siteConfig.advanced.urls.cleanUrls && parentItems && parentItems.length) {
let slugs = [];

for (let i = 0; i < parentItems.length; i++) {
if (rendererInstance.cachedItems.pages[parentItems[i]]) {
slugs.push(rendererInstance.cachedItems.pages[parentItems[i]].slug);
}
}

slugs.push(this.link);
pageSlug = slugs.join('/');
}

if (rendererInstance.siteConfig.advanced.urls.cleanUrls) {
output = baseUrl + '/' + pageSlug + '/';
// In the preview mode we have to load URLs with
// index.html as filesystem on OS doesn't behave
// as the server environment and not redirect to
// a proper URL
if (rendererInstance.previewMode || rendererInstance.siteConfig.advanced.urls.addIndex) {
output += 'index.html';
}
} else {
output = baseUrl + '/' + pageSlug + '.html';
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,23 @@ function socialMetaTagsHelper(rendererInstance, Handlebars) {
siteName = rendererInstance.siteConfig.advanced.metaTitle.replace(/%sitename/g, siteNameValue);
}

// Get tag values according to the current context - listing or single post page
if (
!rendererInstance.siteConfig.advanced.usePageAsFrontpage &&
rendererInstance.siteConfig.advanced.urls.postsPrefix !== '' &&
contextData.data.context.indexOf('index') > -1 &&
rendererInstance.siteConfig.advanced.homepageMetaTitle
) {
let siteNameValue = rendererInstance.siteConfig.name;

if (rendererInstance.siteConfig.displayName) {
siteNameValue = rendererInstance.siteConfig.displayName;
}

siteName = rendererInstance.siteConfig.advanced.homepageMetaTitle.replace(/%sitename/g, siteNameValue);
}

if(contextData.data.context.indexOf('post') === -1 && contextData.data.context.indexOf('page') === -1) {
// Get tag values according to the current context - listing or single post page
// Data for the index/tag listing page
image = contextData.data.website.logo;
title = siteName;
Expand Down
46 changes: 46 additions & 0 deletions app/back-end/modules/render-html/helpers/deleteEmpty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const fs = require('fs');
const path = require('path');
const systemFiles = [
'.DS_Store',
'desktop.ini',
'Thumbs.db'
];

function isSystemFile (file) {
return systemFiles.includes(file);
}

function deleteEmpty (dirPath) {
if (!fs.existsSync(dirPath)) {
return;
}

try {
let files = fs.readdirSync(dirPath);

for (let file of files) {
let fullPath = path.join(dirPath, file);
let stat = fs.statSync(fullPath);

if (stat.isDirectory()) {
deleteEmpty(fullPath);
} else if (isSystemFile(file)) {
fs.unlinkSync(fullPath);
}
}

files = fs.readdirSync(dirPath);
let isDirectoryEmpty = files.length === 0;

if (isDirectoryEmpty) {
fs.rmdirSync(dirPath);
console.log('[OK] Deleted empty directory: ', dirPath);
}
} catch (err) {
console.log('(!) Error during deleting empty directories: ', dirPath , ' | Reason: ', err.message);
}
}

module.exports = {
deleteEmpty
};
4 changes: 2 additions & 2 deletions app/back-end/modules/render-html/helpers/files.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const fs = require('fs-extra');
const list = require('ls-all');
const path = require('path');
const deleteEmpty = require('delete-empty');
const { deleteEmpty } = require('./deleteEmpty.js');
const UtilsHelper = require('./../../../helpers/utils');
const normalizePath = require('normalize-path');
const DiffCopy = require('./diffCopy.js');
Expand Down Expand Up @@ -270,7 +270,7 @@ class Files {

static async removeEmptyDirectories (outputDir) {
let basePathOutput = path.join(outputDir, 'media');
await deleteEmpty(basePathOutput);
deleteEmpty(basePathOutput);
}
}

Expand Down
Loading

0 comments on commit 0047d42

Please sign in to comment.