From ffd885e8a62b5c55cd22f03f34a74349853d27bc Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 19:03:37 +0200 Subject: [PATCH 01/21] Quick fix on margins, not logged --- src/theme/default/elements/_widget/tags.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/theme/default/elements/_widget/tags.html b/src/theme/default/elements/_widget/tags.html index 9d2382d..eb7bc8f 100644 --- a/src/theme/default/elements/_widget/tags.html +++ b/src/theme/default/elements/_widget/tags.html @@ -26,7 +26,7 @@
{{ data.i8n.tags.widget_title }}
-
+
    {% set count = namespace(value=0) %} @@ -43,7 +43,7 @@
    {{ data.i8n.tags.widget_title }}
-
+
    {% set count = namespace(value=0) %} From e788cc0abb7ab8d1952ce3fe816c69ef55e6cee2 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 19:07:17 +0200 Subject: [PATCH 02/21] Issue-67: Implemented support for drafts --- src/application/common/options.py | 14 +- src/application/controller/data_cacher.py | 10 ++ src/application/controller/data_loader.py | 68 ++++++-- src/application/controller/page_cacher.py | 1 - src/application/controller/settings_loader.py | 18 ++- src/application/main.py | 2 +- src/application/model/index.py | 73 +++++---- src/application/model/pages.py | 41 ++++- src/application/model/posts.py | 37 ++++- src/application/model/tags.py | 153 +++++++++--------- src/data/environment/localhost.yml | 1 + src/data/posts/0013_version_1_5_1.md | 36 +++++ 12 files changed, 321 insertions(+), 133 deletions(-) create mode 100644 src/data/posts/0013_version_1_5_1.md diff --git a/src/application/common/options.py b/src/application/common/options.py index 306d856..90dc6d0 100644 --- a/src/application/common/options.py +++ b/src/application/common/options.py @@ -2,11 +2,12 @@ # # Full history: see below # -# Version: 2.2.0 -# Date: 2020-04-26 +# Version: 2.3.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # -# Caching enabled or not +# Features: +# - Support for drafts # ### @@ -29,6 +30,7 @@ class Options(metaclass=Singleton): daemon = False caching = True meta_content_separator = '' + include_drafts = False # SSL settings (for instance for LetsEncrypt) use_ssl = False @@ -46,6 +48,12 @@ class Options(metaclass=Singleton): ### # +# Version: 2.2.0 +# Date: 2020-04-26 +# Author: Yves Vindevogel (vindevoy) +# +# Caching enabled or not +# # Version: 2.1.0 # Date: 2020-04-23 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/controller/data_cacher.py b/src/application/controller/data_cacher.py index 5dc7ced..014eb54 100644 --- a/src/application/controller/data_cacher.py +++ b/src/application/controller/data_cacher.py @@ -1,3 +1,13 @@ +### +# +# Version: 1.0.0 +# Date: 2020-04-17 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# Simple data caching +# +### import logging diff --git a/src/application/controller/data_loader.py b/src/application/controller/data_loader.py index 137ebed..e91912b 100644 --- a/src/application/controller/data_loader.py +++ b/src/application/controller/data_loader.py @@ -2,12 +2,12 @@ # # Full history: see below # -# Version: 1.3.0 -# Date: 2020-04-26 +# Version: 1.4.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # # Features: -# - Caching enabled or not +# - Support for drafts # ### @@ -112,7 +112,12 @@ def index_data(self, page_index): return DataCacher().get_cached(key) common = self.common_data - data, _ = Index().data(page_index, self.posts_directory, self.posts_count) + if Options().include_drafts: + posts = self.posts_files + else: + posts = self.posts_published + + data, _ = Index().data(page_index, posts) # We don't care yet about the introduction content combined = self.__combine(common, data) @@ -143,10 +148,18 @@ def pages_directory(self): def pages_files(self): return self.__get_data('pages_files', Pages(), 'files') + @property + def pages_published(self): + return self.__get_data('pages_files', Pages(), 'files_published') + @property def pages_count(self): return self.__get_data('pages_count', Pages(), 'count') + @property + def pages_count_published(self): + return self.__get_data('pages_count', Pages(), 'count_published') + def pages_data(self, page): key = '/pages/{0}'.format(page) @@ -173,10 +186,18 @@ def posts_directory(self): def posts_files(self): return self.__get_data('posts_files', Posts(), 'files') + @property + def posts_published(self): + return self.__get_data('posts_files_published', Posts(), 'files_published') + @property def posts_count(self): return self.__get_data('posts_count', Posts(), 'count') + @property + def posts_count_published(self): + return self.__get_data('posts_count', Posts(), 'count_published') + def posts_data(self, post): key = '/posts/{0}'.format(post) @@ -199,10 +220,17 @@ def posts_data(self, post): def search_data(self, query, page_index): search_base = [] - for page in self.pages_files: + if Options().include_drafts: + pages = self.pages_files + posts = self.posts_files + else: + pages = self.pages_published + posts = self.posts_published + + for page in pages: search_base.append(page) - for post in self.posts_files: + for post in posts: search_base.append(post) common = self.common_data @@ -225,7 +253,12 @@ def tags_posts_count(self, tag): if Options().caching and DataCacher().cached_already(key): return DataCacher().get_cached(key) - data = Tags().count_posts(self.posts_directory, tag) + if Options().include_drafts: + posts = self.posts_files + else: + posts = self.posts_published + + data = Tags().count_posts(posts, tag) if Options().caching: DataCacher().cache(key, data) @@ -239,7 +272,12 @@ def tags_list(self): if Options().caching and DataCacher().cached_already(key): return DataCacher().get_cached(key) - tags_list = Tags().list(self.posts_directory) + if Options().include_drafts: + posts = self.posts_files + else: + posts = self.posts_published + + tags_list = Tags().list(posts) if Options().caching: DataCacher().cache(key, tags_list) @@ -270,8 +308,13 @@ def tags_data(self, tag, page_index): if Options().caching and DataCacher().cached_already(key): return DataCacher().get_cached(key) + if Options().include_drafts: + posts = self.posts_files + else: + posts = self.posts_published + common = self.common_data - data = Tags().data(self.posts_directory, tag, page_index, self.index_max_posts, self.tags_posts_count(tag)) + data = Tags().data(posts, tag, page_index, self.index_max_posts, self.tags_posts_count(tag)) combined = self.__combine(common, data) if Options().caching: @@ -281,6 +324,13 @@ def tags_data(self, tag, page_index): ### # +# Version: 1.3.0 +# Date: 2020-04-26 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# - Caching enabled or not +# # Version: 1.2.0 # Date: 2020-04-17 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/controller/page_cacher.py b/src/application/controller/page_cacher.py index 900f8af..7781ab4 100644 --- a/src/application/controller/page_cacher.py +++ b/src/application/controller/page_cacher.py @@ -33,4 +33,3 @@ def get_cached(self, key): def cache(self, key, data): self.__logger.info('Caching {0}'.format(key)) self.__cached_pages[key] = data - diff --git a/src/application/controller/settings_loader.py b/src/application/controller/settings_loader.py index 48e6c0a..8b68a76 100644 --- a/src/application/controller/settings_loader.py +++ b/src/application/controller/settings_loader.py @@ -2,12 +2,12 @@ # # Full history: see below # -# Version: 1.5.0 -# Date: 2020-04-28 +# Version: 1.6.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # # Features: -# Handling missing keys and using defaults +# - Support for drafts # ### @@ -142,6 +142,11 @@ def __option_settings(settings_yaml): except KeyError: Options().meta_content_separator = '__________' + try: + Options().include_drafts = settings_yaml['content']['include_drafts'] + except KeyError: + Options().include_drafts = False + try: Options().daemon = settings_yaml['engine']['daemon'] except KeyError: @@ -190,6 +195,13 @@ def __option_settings(settings_yaml): ### # +# Version: 1.5.0 +# Date: 2020-04-28 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# Handling missing keys and using defaults +# # Version: 1.4.0 # Date: 2020-04-23 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/main.py b/src/application/main.py index 0241757..ca63f27 100644 --- a/src/application/main.py +++ b/src/application/main.py @@ -200,4 +200,4 @@ # raise WantWriteError() # OpenSSL.SSL.WantWriteError # -### \ No newline at end of file +### diff --git a/src/application/model/index.py b/src/application/model/index.py index b1f9f97..b03d832 100644 --- a/src/application/model/index.py +++ b/src/application/model/index.py @@ -2,18 +2,17 @@ # # Full history: see below # -# Version: 1.3.0 -# Date: 2020-05-01 +# Version: 1.4.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # # Features: -# - Rewrite date format +# - Support for drafts # ### import logging import math -import os from pathlib import Path @@ -73,7 +72,7 @@ def footer_menu(self): return content - def data(self, page_index, posts_dir, total_posts): + def data(self, page_index, published_posts): self.__logger.debug('data - page_index: {0}'.format(page_index)) data = {} @@ -108,46 +107,45 @@ def data(self, page_index, posts_dir, total_posts): skip_entries = (int(page_index) - 1) * max_entries self.__logger.debug('data - skip_entries: {0}'.format(skip_entries)) - try: - for file in sorted(os.listdir(posts_dir), reverse=True): - count_entries += 1 + for entry in published_posts: + directory = entry['directory'] + file = entry['file'] + count_entries += 1 - # We count the entries, but for pages 2 and more, you don't show them - if skip_entries >= count_entries: - continue + # We count the entries, but for pages 2 and more, you don't show them + if skip_entries >= count_entries: + continue - post, _, post['content'] = Content().read_content(posts_dir, file) + post, _, post['content'] = Content().read_content(directory, file) - stem = Path(file).stem - post['url'] = stem - post['date'] = DateTimeSupport().rewrite_date(post['date']) + stem = Path(file).stem + post['url'] = stem + post['date'] = DateTimeSupport().rewrite_date(post['date']) - self.__logger.debug('data - post: {0}'.format(post)) + self.__logger.debug('data - post: {0}'.format(post)) - if page_index == 1: - if count_entries <= spotlight_entries: - self.__logger.debug('data - post added to spotlight_posts.') - data['spotlight_posts'].append(post) + if page_index == 1: + if count_entries <= spotlight_entries: + self.__logger.debug('data - post added to spotlight_posts.') + data['spotlight_posts'].append(post) - if spotlight_entries < count_entries <= (spotlight_entries + highlight_entries): - self.__logger.debug('data - post added to highlight_posts.') - data['highlight_posts'].append(post) + if spotlight_entries < count_entries <= (spotlight_entries + highlight_entries): + self.__logger.debug('data - post added to highlight_posts.') + data['highlight_posts'].append(post) - if count_entries > (spotlight_entries + highlight_entries): - self.__logger.debug('data - post added to (standard) posts.') - data['posts'].append(post) - - else: + if count_entries > (spotlight_entries + highlight_entries): self.__logger.debug('data - post added to (standard) posts.') data['posts'].append(post) - if count_entries == (max_entries + skip_entries): - self.__logger.debug('data - enough posts for this index page.') - break - except FileNotFoundError: - self.__logger.warning('COULD NOT FIND THE POSTS DIRECTORY {0}'.format(posts_dir)) - pass + else: + self.__logger.debug('data - post added to (standard) posts.') + data['posts'].append(post) + + if count_entries == (max_entries + skip_entries): + self.__logger.debug('data - enough posts for this index page.') + break + total_posts = len(published_posts) total_index_pages = math.ceil(total_posts / max_entries) self.__logger.debug('data - total_posts: {0}'.format(total_posts)) self.__logger.debug('data - total_index_pages: {0}'.format(total_index_pages)) @@ -165,6 +163,13 @@ def data(self, page_index, posts_dir, total_posts): ### # +# Version: 1.3.0 +# Date: 2020-05-01 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# - Rewrite date format +# # Version: 1.2.0 # Date: 2020-04-17 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/model/pages.py b/src/application/model/pages.py index c9ced4b..faafe42 100644 --- a/src/application/model/pages.py +++ b/src/application/model/pages.py @@ -7,8 +7,7 @@ # Author: Yves Vindevogel (vindevoy) # # Features: -# - Removing skipped tags -# - Rewrite date format +# - Support for drafts # ### @@ -51,6 +50,29 @@ def files(self): return files + @property + def files_published(self): + directory = self.directory + files = [] + + for entry in self.files: + file = entry['file'] + meta, _, _ = Content().read_content(directory, file) # only need the meta data + + try: + value = meta['draft'] + draft = bool(value) + + except KeyError: + draft = False + + self.__logger.debug('published_files - {0}/{1} is a draft: {2}'.format(directory, file, draft)) + + if not draft: + files.append(entry) + + return files + @property def count(self): try: @@ -63,6 +85,13 @@ def count(self): return count + @property + def count_published(self): + count = len(self.files_published) + self.__logger.debug('count_published - count: {0}'.format(count)) + + return count + def data(self, page, skip_tags): self.__logger.debug('data - page: {0}'.format(page)) @@ -100,6 +129,14 @@ def data(self, page, skip_tags): ### # +# Version: 1.3.0 +# Date: 2020-05-01 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# - Removing skipped tags +# - Rewrite date format +# # Version: 1.2.0 # Date: 2020-04-17 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/model/posts.py b/src/application/model/posts.py index 3d52517..da52dc3 100644 --- a/src/application/model/posts.py +++ b/src/application/model/posts.py @@ -52,17 +52,42 @@ def files(self): return files @property - def count(self): - try: - count = len(os.listdir(self.directory)) - except FileNotFoundError: - self.__logger.warning('COULD NOT FIND THE POSTS DIRECTORY {0}'.format(self.directory)) - count = 0 + def files_published(self): + directory = self.directory + files = [] + + for entry in self.files: + file = entry['file'] + meta, _, _ = Content().read_content(directory, file) # only need the meta data + + try: + value = meta['draft'] + draft = bool(value) + + except KeyError: + draft = False + + self.__logger.debug('published_files - {0}/{1} is a draft: {2}'.format(directory, file, draft)) + + if not draft: + files.append(entry) + return files + + @property + def count(self): + count = len(self.files) self.__logger.debug('count - count: {0}'.format(count)) return count + @property + def count_published(self): + count = len(self.files_published) + self.__logger.debug('count_published - count: {0}'.format(count)) + + return count + def data(self, post, skip_tags): self.__logger.debug('data - post: {0}'.format(post)) diff --git a/src/application/model/tags.py b/src/application/model/tags.py index 76effa3..2cc1d2f 100644 --- a/src/application/model/tags.py +++ b/src/application/model/tags.py @@ -2,19 +2,17 @@ # # Full history: see below # -# Version: 1.3.0 -# Date: 2020-05-01 +# Version: 1.4.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # # Changes: -# - Moved the tag_label and tag_text methods to a support class in common -# - Rewrite date format +# - Support for drafts # ### import logging import math -import os import string from operator import itemgetter @@ -47,8 +45,8 @@ def skip_tags(self): return tags - def list(self, posts_dir): - self.__logger.debug('list - posts_dir: {0}'.format(posts_dir)) + def list(self, posts): + self.__logger.debug('list - posts: {0}'.format(posts)) settings = Content().load_data_settings_yaml(self.__base_dir) self.__logger.debug('list - settings: {0}'.format(settings)) @@ -56,31 +54,30 @@ def list(self, posts_dir): # Starting with a dictionary as this is the easiest to find existing tags tags = {} - try: - for file in os.listdir(posts_dir): - meta, _, _ = Content().read_content(posts_dir, file) # No need to catch the content + for entry in posts: + directory = entry['directory'] + file = entry['file'] + + meta, _, _ = Content().read_content(directory, file) # No need to catch the content + + if meta['tags'] is None: + continue - if meta['tags'] is None: + for tag in meta['tags']: + label = TagsSupport().tag_label(tag) + + if label in settings['skip_tags']: + self.__logger.debug('list - tag {0} found in skip_tags'.format(tag)) continue - for tag in meta['tags']: - label = TagsSupport().tag_label(tag) - - if label in settings['skip_tags']: - self.__logger.debug('list - tag {0} found in skip_tags'.format(tag)) - continue - - if label in tags.keys(): - self.__logger.debug('list - tag {0} already exists, +1'.format(tag)) - current_count = tags[label]['count'] - tags[label]['count'] = current_count + 1 - else: - self.__logger.debug('list - tag {0} does not already exist'.format(tag)) - data = {'label': label, 'count': 1, 'text': string.capwords(tag)} - tags[label] = data - except FileNotFoundError: - self.__logger.warning('COULD NOT FIND THE POSTS DIRECTORY {0}'.format(posts_dir)) - pass + if label in tags.keys(): + self.__logger.debug('list - tag {0} already exists, +1'.format(tag)) + current_count = tags[label]['count'] + tags[label]['count'] = current_count + 1 + else: + self.__logger.debug('list - tag {0} does not already exist'.format(tag)) + data = {'label': label, 'count': 1, 'text': string.capwords(tag)} + tags[label] = data self.__logger.debug('list - tags: '.format(tags)) @@ -95,8 +92,8 @@ def list(self, posts_dir): return tags_list - def data(self, posts_dir, tag, page_index, index_max_posts, count_tag_posts): - self.__logger.debug('data - posts_dir: {0}'.format(posts_dir)) + def data(self, posts, tag, page_index, index_max_posts, count_tag_posts): + self.__logger.debug('data - posts: {0}'.format(posts)) self.__logger.debug('data - tag: {0}'.format(tag)) self.__logger.debug('data - page_index tags: {0}'.format(page_index)) self.__logger.debug('data - index_max_posts tags: {0}'.format(index_max_posts)) @@ -110,46 +107,46 @@ def data(self, posts_dir, tag, page_index, index_max_posts, count_tag_posts): self.__logger.debug('data - max_entries: {0}'.format(max_entries)) self.__logger.debug('data - skip_entries: {0}'.format(skip_entries)) - try: - for file in sorted(os.listdir(posts_dir), reverse=True): - post, _, post['content'] = Content().read_content(posts_dir, file) + for entry in posts: + directory = entry['directory'] + file = entry['file'] - if post['tags'] is None: - continue + post, _, post['content'] = Content().read_content(directory, file) - self.__logger.debug('data - post: {0}'.format(post)) + if post['tags'] is None: + continue - must_include = False + self.__logger.debug('data - post: {0}'.format(post)) - for tag_raw in post['tags']: - if TagsSupport().tag_label(tag_raw) == tag: - must_include = True - break + must_include = False - self.__logger.debug('data - must_include: {0}'.format(must_include)) + for tag_raw in post['tags']: + if TagsSupport().tag_label(tag_raw) == tag: + must_include = True + break - if must_include: - count_entries += 1 + self.__logger.debug('data - must_include: {0}'.format(must_include)) - # We count the entries, but for pages 2 and more, you don't show them - if skip_entries >= count_entries: - self.__logger.debug('data - post skipped}') - continue - else: - self.__logger.debug('data - post added') + if must_include: + count_entries += 1 + + # We count the entries, but for pages 2 and more, you don't show them + if skip_entries >= count_entries: + self.__logger.debug('data - post skipped}') + continue + else: + self.__logger.debug('data - post added') - stem = Path(file).stem - post['url'] = stem + stem = Path(file).stem + post['url'] = stem - post['date'] = DateTimeSupport().rewrite_date(post['date']) + post['date'] = DateTimeSupport().rewrite_date(post['date']) - data['posts'].append(post) + data['posts'].append(post) - if count_entries == (max_entries + skip_entries): - self.__logger.debug('data - enough posts') - break - except FileNotFoundError: - pass + if count_entries == (max_entries + skip_entries): + self.__logger.debug('data - enough posts') + break data['tag'] = {'name': TagsSupport().tag_text(tag), 'path': tag} @@ -162,26 +159,26 @@ def data(self, posts_dir, tag, page_index, index_max_posts, count_tag_posts): return data - def count_posts(self, posts_dir, tag): + def count_posts(self, posts, tag): self.__logger.debug('count_posts - tag: {0}'.format(tag)) - self.__logger.debug('count_posts - posts_dir: {0}'.format(posts_dir)) + self.__logger.debug('count_posts - posts: {0}'.format(posts)) count_entries = 0 - try: - for file in os.listdir(posts_dir): - post, _, _ = Content().read_content(posts_dir, file) + for entry in posts: + directory = entry['directory'] + file = entry['file'] - if post['tags'] is None: - continue + post, _, _ = Content().read_content(directory, file) + + if post['tags'] is None: + continue - for tag_raw in post['tags']: - if TagsSupport().tag_label(tag_raw) == tag: - count_entries += 1 - self.__logger.debug('count_posts - file {0} includes tag '.format(file)) - break - except FileNotFoundError: - pass + for tag_raw in post['tags']: + if TagsSupport().tag_label(tag_raw) == tag: + count_entries += 1 + self.__logger.debug('count_posts - file {0} includes tag '.format(file)) + break self.__logger.debug('count_posts - tag {0} has {1} posts'.format(tag, count_entries)) @@ -189,6 +186,14 @@ def count_posts(self, posts_dir, tag): ### # +# Version: 1.3.0 +# Date: 2020-05-01 +# Author: Yves Vindevogel (vindevoy) +# +# Changes: +# - Moved the tag_label and tag_text methods to a support class in common +# - Rewrite date format +# # Version: 1.2.1 # Date: 2020-04-23 # Author: Yves Vindevogel (vindevoy) diff --git a/src/data/environment/localhost.yml b/src/data/environment/localhost.yml index 34a2cbc..7d7bfeb 100644 --- a/src/data/environment/localhost.yml +++ b/src/data/environment/localhost.yml @@ -2,6 +2,7 @@ content: meta_content_separator: "----------" + include_drafts: False directories: theme: diff --git a/src/data/posts/0013_version_1_5_1.md b/src/data/posts/0013_version_1_5_1.md new file mode 100644 index 0000000..9efa942 --- /dev/null +++ b/src/data/posts/0013_version_1_5_1.md @@ -0,0 +1,36 @@ +--- + +title: "Release v1.5.1" + +author: "Yves Vindevogel" +date: "2020-05-07" + +image: "cherry3.jpg" + +summary: "Releasing a minor bug update" + +draft: True + +tags: + - History + - Bug fixes + +---------- + +This is a minor bug update, just one small bug, sorry. + + +## Release info + +- author: Yves Vindevogel (vindevoy) +- date: 2020-05-07 + +## Bug Fixes + +- There was a problem with the search results. The font weight (bold) of found text in the search results is now case-insensitive. + +### Github + +For more information on this release, see the issues for this milestone: + +- [https://github.com/vindevoy/cherryblog/milestone/14](https://github.com/vindevoy/cherryblog/milestone/14) \ No newline at end of file From 84f69b76b957e8ba11b611dc464abf94d9c052ad Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Wed, 6 May 2020 17:32:41 +0200 Subject: [PATCH 03/21] Updated version info with v1.5.1 --- src/data/codeversion/settings.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/codeversion/settings.yml b/src/data/codeversion/settings.yml index 14861bc..707d8c5 100644 --- a/src/data/codeversion/settings.yml +++ b/src/data/codeversion/settings.yml @@ -2,4 +2,4 @@ text: - 'Production: v.1.5.0 (master branch)' - - 'Next version: v.1.6.0 (starting soon)' \ No newline at end of file + - 'Next version: v.1.5.1 (develop branch)' \ No newline at end of file From e80add2b837215e15528a81e1aadeed4ae4563ce Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Wed, 6 May 2020 17:28:58 +0200 Subject: [PATCH 04/21] Added the search in the introduction From e91f92e9d67627a7ca6f8ea7a78e851659a662f6 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 19:21:11 +0200 Subject: [PATCH 05/21] Added announcement v1.5.1 --- src/data/environment/localhost.yml | 2 +- src/data/posts/0013_version_1_5_1.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/environment/localhost.yml b/src/data/environment/localhost.yml index 7d7bfeb..183e49d 100644 --- a/src/data/environment/localhost.yml +++ b/src/data/environment/localhost.yml @@ -2,7 +2,7 @@ content: meta_content_separator: "----------" - include_drafts: False + include_drafts: True directories: theme: diff --git a/src/data/posts/0013_version_1_5_1.md b/src/data/posts/0013_version_1_5_1.md index 9efa942..25e0ceb 100644 --- a/src/data/posts/0013_version_1_5_1.md +++ b/src/data/posts/0013_version_1_5_1.md @@ -9,7 +9,7 @@ image: "cherry3.jpg" summary: "Releasing a minor bug update" -draft: True +draft: False tags: - History From 24e71ea2ba05e564ba15c7ab83087987e278f758 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 19:47:40 +0200 Subject: [PATCH 06/21] New version in widget --- src/data/codeversion/settings.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/codeversion/settings.yml b/src/data/codeversion/settings.yml index 707d8c5..31940a4 100644 --- a/src/data/codeversion/settings.yml +++ b/src/data/codeversion/settings.yml @@ -1,5 +1,5 @@ --- text: - - 'Production: v.1.5.0 (master branch)' - - 'Next version: v.1.5.1 (develop branch)' \ No newline at end of file + - 'Production: v.1.5.1 (master branch)' + - 'Next version: v.1.6.0 (develop branch)' \ No newline at end of file From d3b5a06d1b3a70cb1c2de42e11fca712b36b5343 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 19:47:56 +0200 Subject: [PATCH 07/21] Issue-37: Added html minify --- Makefile | 19 +++++++--- src/application/controller/application.py | 45 +++++++++++++++-------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index ca60ab3..841a83a 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,11 @@ ### # -# Version: 1.2.1 -# Date: 2020-04-25 +# Version: 1.3.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # -# Fixes: -# - all logging is now in application.log instead of ENVIRONMENT.log (settings determine it for the run) -# - better history generation +# Features: +# - dependency for django-htmlmin # ### @@ -59,6 +58,8 @@ dependencies: @pip3 install jinja2 @pip3 install pyyaml @pip3 install markdown + @pip3 install django-htmlmin + @echo '[OK] Dependencies in Python installed' @@ -113,6 +114,14 @@ stop: ### # +# Version: 1.2.1 +# Date: 2020-04-25 +# Author: Yves Vindevogel (vindevoy) +# +# Fixes: +# - all logging is now in application.log instead of ENVIRONMENT.log (settings determine it for the run) +# - better history generation +# # Version: 1.2.0 # Date: 2020-04-11 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/controller/application.py b/src/application/controller/application.py index 686c6b8..1b5aa11 100644 --- a/src/application/controller/application.py +++ b/src/application/controller/application.py @@ -2,15 +2,17 @@ # # Full history: see below # -# Version: 2.3.0 -# Date: 2020-04-26 +# Version: 2.4.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # -# Caching enabled or not +# Using HTML minify # ### import cherrypy +from htmlmin.minify import html_minify + import logging from datetime import datetime @@ -35,7 +37,7 @@ def index(self, page_index=1, **_): start = datetime.now() if Options().caching and PageCacher().cached_already(request): - rendered = PageCacher().get_cached(request) + minified = PageCacher().get_cached(request) else: data = DataLoader().index_data(page_index) @@ -43,14 +45,15 @@ def index(self, page_index=1, **_): template = TemplateLoader().get_template('screen_index.html') rendered = template.render(data=data) + minified = html_minify(rendered) if Options().caching: - PageCacher().cache(request, rendered) + PageCacher().cache(request, minified) finished = datetime.now() self.__logger.info('{0} {1}'.format(request, finished - start)) - return rendered + return minified @cherrypy.expose def pages(self, page, **_): @@ -58,7 +61,7 @@ def pages(self, page, **_): start = datetime.now() if Options().caching and PageCacher().cached_already(request): - rendered = PageCacher().get_cached(request) + minified = PageCacher().get_cached(request) else: # page on the URL: http://www.yoursite.ext/pages/page @@ -67,14 +70,15 @@ def pages(self, page, **_): template = TemplateLoader().get_template('screen_page.html') rendered = template.render(data=data) + minified = html_minify(rendered) if Options().caching: - PageCacher().cache(request, rendered) + PageCacher().cache(request, minified) finished = datetime.now() self.__logger.info('{0} {1}'.format(request, finished - start)) - return rendered + return minified @cherrypy.expose def posts(self, post, **_): @@ -82,7 +86,7 @@ def posts(self, post, **_): start = datetime.now() if Options().caching and PageCacher().cached_already(request): - rendered = PageCacher().get_cached(request) + minified = PageCacher().get_cached(request) else: data = DataLoader().posts_data(post) @@ -90,14 +94,15 @@ def posts(self, post, **_): template = TemplateLoader().get_template('screen_post.html') rendered = template.render(data=data) + minified = html_minify(rendered) if Options().caching: - PageCacher().cache(request, rendered) + PageCacher().cache(request, minified) finished = datetime.now() self.__logger.info('{0} {1}'.format(request, finished - start)) - return rendered + return minified @cherrypy.expose def tags(self, tag, page_index=1, **_): @@ -105,7 +110,7 @@ def tags(self, tag, page_index=1, **_): start = datetime.now() if Options().caching and PageCacher().cached_already(request): - rendered = PageCacher().get_cached(request) + minified = PageCacher().get_cached(request) else: data = DataLoader().tags_data(tag, page_index) @@ -113,14 +118,15 @@ def tags(self, tag, page_index=1, **_): template = TemplateLoader().get_template('screen_tag.html') rendered = template.render(data=data) + minified = html_minify(rendered) if Options().caching: - PageCacher().cache(request, rendered) + PageCacher().cache(request, minified) finished = datetime.now() self.__logger.info('{0} {1}'.format(request, finished - start)) - return rendered + return minified @cherrypy.expose def search(self, page_index=1, query='', **_): @@ -132,11 +138,12 @@ def search(self, page_index=1, query='', **_): template = TemplateLoader().get_template('screen_search.html') rendered = template.render(data=data) + minified = html_minify(rendered) finished = datetime.now() self.__logger.info('{0} {1}'.format(request, finished - start)) - return rendered + return minified # @cherrypy.expose # def print_page(self, page, **_): @@ -160,6 +167,12 @@ def search(self, page_index=1, query='', **_): ### # +# Version: 2.3.0 +# Date: 2020-04-26 +# Author: Yves Vindevogel (vindevoy) +# +# Caching enabled or not +# # Version: 2.2.0 # Date: 2020-04-22 # Author: Yves Vindevogel (vindevoy) From f28db636db56f97719d431269592e567b203944d Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 21:16:26 +0200 Subject: [PATCH 08/21] Issue-111: Google sitemap --- .gitignore | 3 +- Makefile | 15 +++- src/application/controller/application.py | 3 +- src/application/sitemap.py | 98 +++++++++++++++++++++++ src/data/environment/localhost.yml | 4 + src/data/environment/production.sample | 5 ++ 6 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 src/application/sitemap.py diff --git a/.gitignore b/.gitignore index d8c0f77..d1027f6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ tmp/ download/ log/ -production.yml \ No newline at end of file +production.yml +sitemap.xml \ No newline at end of file diff --git a/Makefile b/Makefile index 841a83a..3c75365 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ # # Features: # - dependency for django-htmlmin +# - create sitemap.xml # ### @@ -100,11 +101,21 @@ history: @echo '[OK] history copied to pages' -develop: +sitemap: + @mkdir -p ./src/data/sitemap + @python3 ./src/application/sitemap.py + + + @echo '[OK] sitemap.xml created' + +google: sitemap + @curl http://www.google.com/ping?sitemap=https://cherryblog.org/sitemap.xml > /dev/null + +develop: sitemap @mkdir -p ./log @python3 ./src/application/main.py 2>&1 | tee ./log/application.log -production: +production: sitemap @mkdir -p /var/log/cherryblog @python3 ./src/application/main.py --env production 2>&1 | tee /var/log/cherryblog/application.log & diff --git a/src/application/controller/application.py b/src/application/controller/application.py index 1b5aa11..0340713 100644 --- a/src/application/controller/application.py +++ b/src/application/controller/application.py @@ -11,11 +11,10 @@ ### import cherrypy -from htmlmin.minify import html_minify - import logging from datetime import datetime +from htmlmin.minify import html_minify from common.options import Options from common.singleton import Singleton diff --git a/src/application/sitemap.py b/src/application/sitemap.py new file mode 100644 index 0000000..2c39f78 --- /dev/null +++ b/src/application/sitemap.py @@ -0,0 +1,98 @@ +### +# +# Full history: see below +# +# Version: 1.0.0 +# Date: 2020-05-07 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# - Build a sitemap +# +### + +import logging +import os + +from pathlib import Path + +from common.options import Options +from common.content import Content +from controller.data_loader import DataLoader +from controller.logging_loader import LoggingLoader +from controller.settings_loader import SettingsLoader + +environment = 'localhost' +data_dir = os.path.join(os.getcwd(), 'src', 'data') + +Options().environment = environment +Options().data_dir = data_dir + +settings = SettingsLoader(environment).parse() + +LoggingLoader().configure() + +logger = logging.getLogger('SITEMAP') + +# Override the drafts because Google will never find them in production most likely +Options().include_drafts = False + +xml = '\n' +xml += '\n' + +priority = 1.0 + +page_priorities = {'about': {'priority': 1.0, 'update': 'monthly'}, + 'documentation': {'priority': 0.9, 'update': 'monthly'}, + 'credits': {'priority': 0.1, 'update': 'yearly'} + } + +for entry in DataLoader().posts_published: + file = entry['file'] + stem = Path(file).stem + + logger.info('Parsing {0}'.format(file)) + + meta, _, _ = Content().read_content('posts', file) + + xml += ' \n' + xml += ' https://cherryblog.org/posts/{0}\n'.format(stem) + xml += ' {0}\n'.format(meta['date']) + xml += ' never\n' + xml += ' {0}\n'.format(round(priority, 2)) + xml += ' \n' + + if priority > 0.5: + priority = round(priority - 0.1, 2) + +for entry in DataLoader().pages_published: + file = entry['file'] + stem = Path(file).stem + + logger.info('Parsing {0}'.format(file)) + + meta, _, _ = Content().read_content('pages', file) + + try: + priority = page_priorities[stem]['priority'] + except KeyError: + priority = 0.5 + + try: + update = page_priorities[stem]['update'] + except KeyError: + update = 'monthly' + + xml += ' \n' + xml += ' https://cherryblog.org/pages/{0}\n'.format(stem) + xml += ' {0}\n'.format(meta['date']) + xml += ' {0}\n'.format(update) + xml += ' {0}\n'.format(round(priority, 2)) + xml += ' \n' + +xml += '\n' + + +sitemap_file = open(os.path.join(data_dir, 'sitemap', 'sitemap.xml'), 'w') +sitemap_file.write(xml) +sitemap_file.close() diff --git a/src/data/environment/localhost.yml b/src/data/environment/localhost.yml index 183e49d..d29e905 100644 --- a/src/data/environment/localhost.yml +++ b/src/data/environment/localhost.yml @@ -35,6 +35,10 @@ tools: - url: '/static' absolute: False path: 'src/theme/default/static' + staticfiles: + - url: '/sitemap.xml' + absolute: False + path: 'src/data/sitemap/sitemap.xml' user: privileges: False diff --git a/src/data/environment/production.sample b/src/data/environment/production.sample index c200b70..f1da96e 100644 --- a/src/data/environment/production.sample +++ b/src/data/environment/production.sample @@ -2,6 +2,7 @@ content: meta_content_separator: "----------" + include_drafts: False directories: theme: @@ -34,6 +35,10 @@ tools: - url: '/static' absolute: False path: 'src/theme/default/static' + staticfiles: + - url: '/sitemap.xml' + absolute: False + path: 'src/data/sitemap/sitemap.xml' user: privileges: True From 80e6a7d77155b66a1367c3f3f748ad021e7ef248 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Fri, 8 May 2020 15:33:24 +0200 Subject: [PATCH 09/21] Applying stash --- src/application/controller/remapper.py | 50 +++++++++++++++++++++++ src/application/model/mapping.py | 56 ++++++++++++++++++++++++++ src/data/mapping/settings.yml | 7 ++++ 3 files changed, 113 insertions(+) create mode 100644 src/application/controller/remapper.py create mode 100644 src/application/model/mapping.py create mode 100644 src/data/mapping/settings.yml diff --git a/src/application/controller/remapper.py b/src/application/controller/remapper.py new file mode 100644 index 0000000..eaa3d64 --- /dev/null +++ b/src/application/controller/remapper.py @@ -0,0 +1,50 @@ +### +# +# Version: 1.0.0 +# Date: 2020-05-08 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# Remapping of incoming requests to content documents +# Remapping of content to outgoing URLs +# +### + +import logging + +from common.options import Options +from common.singleton import Singleton + + +class Remapper(metaclass=Singleton): + outgoing_content = None + incoming_content = None + + __logger = None + + def __init__(self): + self.__logger = logging.getLogger('REMAPPER') + self.__logger.setLevel(Options().default_logging_level) + + def remap_document(self, doc): + self.__logger.debug('remap_document - doc: {0}'.format(doc)) + + return self.__remap(doc, self.outgoing_content, 'OUT') + + def remap_url(self, url): + self.__logger.debug('remap_url - url: {0}'.format(url)) + + return self.__remap(url, self.incoming_content, 'IN') + + def __remap(self, mapping, mappings, way): + self.__logger.debug('__remap - mapping: {0}'.format(mapping)) + self.__logger.debug('__remap - mappings: {0}'.format(mappings)) + + if mapping in mappings: + mapped = mappings[mapping] + self.__logger.debug('__remap - mapped: {0}'.format(mapped)) + + self.__logger.info('{0}: {1} -> {2}'.format(way, mapping, mapped)) + return mapped + else: + return mapping diff --git a/src/application/model/mapping.py b/src/application/model/mapping.py new file mode 100644 index 0000000..6d7f6d1 --- /dev/null +++ b/src/application/model/mapping.py @@ -0,0 +1,56 @@ +### +# +# Full history: see below +# +# Version: 1.0.0 +# Date: 2020-05-07 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# - Mapping of URLs to physical files +# +### + +import logging + +from common.options import Options +from common.content import Content +from common.singleton import Singleton + + +class Mapping(metaclass=Singleton): + __base_dir = 'mapping' + __logger = None + + incoming = None + outgoing = None + + def __init__(self): + self.__logger = logging.getLogger('MODEL.MAPPING') + self.__logger.setLevel(Options().default_logging_level) + + self.__data() + + def __data(self): + content = Content().load_data_settings_yaml(self.__base_dir) + self.__logger.debug('__data - content: {0}'.format(content)) + + incoming = {} + outgoing = {} + + for mapping in content['content']: + self.__logger.debug('__data - mapping: {0}'.format(mapping)) + + target = mapping['target'] + source = mapping['source'] + self.__logger.debug('__data - target: {0}'.format(target)) + self.__logger.debug('__data - source: {0}'.format(source)) + + incoming[target] = source + self.__logger.info('mapping incoming URL \'{0}\' to source \'{1}\''.format(target, source)) + + outgoing[source] = target + self.__logger.info('mapping outgoing source \'{0}\' to URL \'{1}\''.format(source, target)) + + self.incoming = incoming + self.outgoing = outgoing diff --git a/src/data/mapping/settings.yml b/src/data/mapping/settings.yml new file mode 100644 index 0000000..8af32ef --- /dev/null +++ b/src/data/mapping/settings.yml @@ -0,0 +1,7 @@ +--- + +content: + - target: 'posts/announcement' + source: 'posts/0001_announcement' + - target: 'posts/version_1.0.0' + source: 'posts/0002_version_1_0_0' From bd672354adea5914210251fa54cfbf430e629f71 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Fri, 8 May 2020 15:34:05 +0200 Subject: [PATCH 10/21] From stash --- src/application/controller/application.py | 11 ++++++++++- src/application/controller/data_loader.py | 8 ++++++++ src/application/main.py | 5 +++++ src/application/model/index.py | 6 +++++- src/application/model/posts.py | 2 +- src/theme/default/elements/_html/highlight_post.html | 2 +- src/theme/default/elements/_html/spotlight_post.html | 2 +- src/theme/default/elements/_html/standard_post.html | 2 +- 8 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/application/controller/application.py b/src/application/controller/application.py index 0340713..a898930 100644 --- a/src/application/controller/application.py +++ b/src/application/controller/application.py @@ -20,6 +20,7 @@ from common.singleton import Singleton from controller.data_loader import DataLoader from controller.page_cacher import PageCacher +from controller.remapper import Remapper from view.templateloader import TemplateLoader @@ -81,13 +82,21 @@ def pages(self, page, **_): @cherrypy.expose def posts(self, post, **_): - request = '/posts/{0}'.format(post) start = datetime.now() + request = 'posts/{0}'.format(post) + self.__logger.info('posts - request: {0}'.format(request)) if Options().caching and PageCacher().cached_already(request): minified = PageCacher().get_cached(request) else: + remapped = Remapper().remap_url(request) + self.__logger.info('posts - remapped: {0}'.format(remapped)) + + if request != remapped: + post = remapped.split('/')[1] + self.__logger.info('posts - post: {0}'.format(post)) + data = DataLoader().posts_data(post) data['url'] = request diff --git a/src/application/controller/data_loader.py b/src/application/controller/data_loader.py index e91912b..36d5c5b 100644 --- a/src/application/controller/data_loader.py +++ b/src/application/controller/data_loader.py @@ -20,6 +20,7 @@ from model.i8n import I8N from model.important_news import ImportantNews from model.index import Index +from model.mapping import Mapping from model.pages import Pages from model.posts import Posts from model.search import Search @@ -139,6 +140,13 @@ def index_spotlight_posts(self): def index_highlight_posts(self): return self.__get_data('index_highlight_posts', Index(), 'highlight_posts') + # mapping + def mapping_incoming(self): + return self.__get_data('mapping_incoming', Mapping(), 'incoming') + + def mapping_outgoing(self): + return self.__get_data('mapping_outgoing', Mapping(), 'outgoing') + # pages @property def pages_directory(self): diff --git a/src/application/main.py b/src/application/main.py index ca63f27..421da0c 100644 --- a/src/application/main.py +++ b/src/application/main.py @@ -25,6 +25,7 @@ from controller.application import Application from controller.data_loader import DataLoader from controller.logging_loader import LoggingLoader +from controller.remapper import Remapper from controller.settings_loader import SettingsLoader __application = 'CherryBlog' @@ -78,6 +79,10 @@ logger.info('Default date input format set to \'{0}\'.'.format(DateTimeSupport().input_format)) logger.info('Default date output format set to \'{0}\'.'.format(DateTimeSupport().output_format)) + # Loading the remapping + Remapper().outgoing_content = DataLoader().mapping_outgoing() + Remapper().incoming_content = DataLoader().mapping_incoming() + if Options().use_ssl: # vindevoy - 2020-04-25 # You must use the builtin SSL option. If you use pyOpenSLL you get the error below (see history) diff --git a/src/application/model/index.py b/src/application/model/index.py index b03d832..2f3e5af 100644 --- a/src/application/model/index.py +++ b/src/application/model/index.py @@ -20,6 +20,7 @@ from common.datetime_support import DateTimeSupport from common.options import Options from common.singleton import Singleton +from controller.remapper import Remapper class Index(metaclass=Singleton): @@ -119,7 +120,10 @@ def data(self, page_index, published_posts): post, _, post['content'] = Content().read_content(directory, file) stem = Path(file).stem - post['url'] = stem + url = 'posts/{0}'.format(stem) + url = Remapper().remap_document(url) + + post['url'] = url post['date'] = DateTimeSupport().rewrite_date(post['date']) self.__logger.debug('data - post: {0}'.format(post)) diff --git a/src/application/model/posts.py b/src/application/model/posts.py index da52dc3..33fbccd 100644 --- a/src/application/model/posts.py +++ b/src/application/model/posts.py @@ -107,7 +107,7 @@ def data(self, post, skip_tags): tags.append(TagsSupport().tag_text(tag)) else: self.__logger.debug('data - removing skipped tag: {0}'.format(tag)) - except KeyError: + except TypeError: pass data['post']['tags'] = tags diff --git a/src/theme/default/elements/_html/highlight_post.html b/src/theme/default/elements/_html/highlight_post.html index 77a747d..eaedd7b 100644 --- a/src/theme/default/elements/_html/highlight_post.html +++ b/src/theme/default/elements/_html/highlight_post.html @@ -18,7 +18,7 @@ {% with author = post.author, date = post.date %} diff --git a/src/theme/default/elements/_html/spotlight_post.html b/src/theme/default/elements/_html/spotlight_post.html index 179e479..9a20bb3 100644 --- a/src/theme/default/elements/_html/spotlight_post.html +++ b/src/theme/default/elements/_html/spotlight_post.html @@ -18,7 +18,7 @@ {% with author = post.author, date = post.date %} diff --git a/src/theme/default/elements/_html/standard_post.html b/src/theme/default/elements/_html/standard_post.html index 2eae580..be86068 100644 --- a/src/theme/default/elements/_html/standard_post.html +++ b/src/theme/default/elements/_html/standard_post.html @@ -16,7 +16,7 @@ {% with author = post.author, date = post.date %} From 63488192412628ccef1353b8a94f5552090ef0be Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 19:03:37 +0200 Subject: [PATCH 11/21] Quick fix on margins, not logged --- src/theme/default/elements/_widget/tags.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/theme/default/elements/_widget/tags.html b/src/theme/default/elements/_widget/tags.html index 9d2382d..eb7bc8f 100644 --- a/src/theme/default/elements/_widget/tags.html +++ b/src/theme/default/elements/_widget/tags.html @@ -26,7 +26,7 @@
    {{ data.i8n.tags.widget_title }}
-
+
    {% set count = namespace(value=0) %} @@ -43,7 +43,7 @@
    {{ data.i8n.tags.widget_title }}
-
+
    {% set count = namespace(value=0) %} From d894f5a9a02fb29a1ca3e3f67587b7fef0eec427 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 19:07:17 +0200 Subject: [PATCH 12/21] Issue-67: Implemented support for drafts --- src/application/common/options.py | 14 +- src/application/controller/data_cacher.py | 10 ++ src/application/controller/data_loader.py | 68 ++++++-- src/application/controller/page_cacher.py | 1 - src/application/controller/settings_loader.py | 18 ++- src/application/main.py | 2 +- src/application/model/index.py | 73 +++++---- src/application/model/pages.py | 32 ++++ src/application/model/posts.py | 37 ++++- src/application/model/tags.py | 153 +++++++++--------- src/data/environment/localhost.yml | 1 + src/data/posts/0013_version_1_5_1.md | 36 +++++ 12 files changed, 314 insertions(+), 131 deletions(-) create mode 100644 src/data/posts/0013_version_1_5_1.md diff --git a/src/application/common/options.py b/src/application/common/options.py index 306d856..90dc6d0 100644 --- a/src/application/common/options.py +++ b/src/application/common/options.py @@ -2,11 +2,12 @@ # # Full history: see below # -# Version: 2.2.0 -# Date: 2020-04-26 +# Version: 2.3.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # -# Caching enabled or not +# Features: +# - Support for drafts # ### @@ -29,6 +30,7 @@ class Options(metaclass=Singleton): daemon = False caching = True meta_content_separator = '' + include_drafts = False # SSL settings (for instance for LetsEncrypt) use_ssl = False @@ -46,6 +48,12 @@ class Options(metaclass=Singleton): ### # +# Version: 2.2.0 +# Date: 2020-04-26 +# Author: Yves Vindevogel (vindevoy) +# +# Caching enabled or not +# # Version: 2.1.0 # Date: 2020-04-23 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/controller/data_cacher.py b/src/application/controller/data_cacher.py index 5dc7ced..014eb54 100644 --- a/src/application/controller/data_cacher.py +++ b/src/application/controller/data_cacher.py @@ -1,3 +1,13 @@ +### +# +# Version: 1.0.0 +# Date: 2020-04-17 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# Simple data caching +# +### import logging diff --git a/src/application/controller/data_loader.py b/src/application/controller/data_loader.py index 137ebed..e91912b 100644 --- a/src/application/controller/data_loader.py +++ b/src/application/controller/data_loader.py @@ -2,12 +2,12 @@ # # Full history: see below # -# Version: 1.3.0 -# Date: 2020-04-26 +# Version: 1.4.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # # Features: -# - Caching enabled or not +# - Support for drafts # ### @@ -112,7 +112,12 @@ def index_data(self, page_index): return DataCacher().get_cached(key) common = self.common_data - data, _ = Index().data(page_index, self.posts_directory, self.posts_count) + if Options().include_drafts: + posts = self.posts_files + else: + posts = self.posts_published + + data, _ = Index().data(page_index, posts) # We don't care yet about the introduction content combined = self.__combine(common, data) @@ -143,10 +148,18 @@ def pages_directory(self): def pages_files(self): return self.__get_data('pages_files', Pages(), 'files') + @property + def pages_published(self): + return self.__get_data('pages_files', Pages(), 'files_published') + @property def pages_count(self): return self.__get_data('pages_count', Pages(), 'count') + @property + def pages_count_published(self): + return self.__get_data('pages_count', Pages(), 'count_published') + def pages_data(self, page): key = '/pages/{0}'.format(page) @@ -173,10 +186,18 @@ def posts_directory(self): def posts_files(self): return self.__get_data('posts_files', Posts(), 'files') + @property + def posts_published(self): + return self.__get_data('posts_files_published', Posts(), 'files_published') + @property def posts_count(self): return self.__get_data('posts_count', Posts(), 'count') + @property + def posts_count_published(self): + return self.__get_data('posts_count', Posts(), 'count_published') + def posts_data(self, post): key = '/posts/{0}'.format(post) @@ -199,10 +220,17 @@ def posts_data(self, post): def search_data(self, query, page_index): search_base = [] - for page in self.pages_files: + if Options().include_drafts: + pages = self.pages_files + posts = self.posts_files + else: + pages = self.pages_published + posts = self.posts_published + + for page in pages: search_base.append(page) - for post in self.posts_files: + for post in posts: search_base.append(post) common = self.common_data @@ -225,7 +253,12 @@ def tags_posts_count(self, tag): if Options().caching and DataCacher().cached_already(key): return DataCacher().get_cached(key) - data = Tags().count_posts(self.posts_directory, tag) + if Options().include_drafts: + posts = self.posts_files + else: + posts = self.posts_published + + data = Tags().count_posts(posts, tag) if Options().caching: DataCacher().cache(key, data) @@ -239,7 +272,12 @@ def tags_list(self): if Options().caching and DataCacher().cached_already(key): return DataCacher().get_cached(key) - tags_list = Tags().list(self.posts_directory) + if Options().include_drafts: + posts = self.posts_files + else: + posts = self.posts_published + + tags_list = Tags().list(posts) if Options().caching: DataCacher().cache(key, tags_list) @@ -270,8 +308,13 @@ def tags_data(self, tag, page_index): if Options().caching and DataCacher().cached_already(key): return DataCacher().get_cached(key) + if Options().include_drafts: + posts = self.posts_files + else: + posts = self.posts_published + common = self.common_data - data = Tags().data(self.posts_directory, tag, page_index, self.index_max_posts, self.tags_posts_count(tag)) + data = Tags().data(posts, tag, page_index, self.index_max_posts, self.tags_posts_count(tag)) combined = self.__combine(common, data) if Options().caching: @@ -281,6 +324,13 @@ def tags_data(self, tag, page_index): ### # +# Version: 1.3.0 +# Date: 2020-04-26 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# - Caching enabled or not +# # Version: 1.2.0 # Date: 2020-04-17 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/controller/page_cacher.py b/src/application/controller/page_cacher.py index 900f8af..7781ab4 100644 --- a/src/application/controller/page_cacher.py +++ b/src/application/controller/page_cacher.py @@ -33,4 +33,3 @@ def get_cached(self, key): def cache(self, key, data): self.__logger.info('Caching {0}'.format(key)) self.__cached_pages[key] = data - diff --git a/src/application/controller/settings_loader.py b/src/application/controller/settings_loader.py index 48e6c0a..8b68a76 100644 --- a/src/application/controller/settings_loader.py +++ b/src/application/controller/settings_loader.py @@ -2,12 +2,12 @@ # # Full history: see below # -# Version: 1.5.0 -# Date: 2020-04-28 +# Version: 1.6.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # # Features: -# Handling missing keys and using defaults +# - Support for drafts # ### @@ -142,6 +142,11 @@ def __option_settings(settings_yaml): except KeyError: Options().meta_content_separator = '__________' + try: + Options().include_drafts = settings_yaml['content']['include_drafts'] + except KeyError: + Options().include_drafts = False + try: Options().daemon = settings_yaml['engine']['daemon'] except KeyError: @@ -190,6 +195,13 @@ def __option_settings(settings_yaml): ### # +# Version: 1.5.0 +# Date: 2020-04-28 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# Handling missing keys and using defaults +# # Version: 1.4.0 # Date: 2020-04-23 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/main.py b/src/application/main.py index 0241757..ca63f27 100644 --- a/src/application/main.py +++ b/src/application/main.py @@ -200,4 +200,4 @@ # raise WantWriteError() # OpenSSL.SSL.WantWriteError # -### \ No newline at end of file +### diff --git a/src/application/model/index.py b/src/application/model/index.py index b1f9f97..b03d832 100644 --- a/src/application/model/index.py +++ b/src/application/model/index.py @@ -2,18 +2,17 @@ # # Full history: see below # -# Version: 1.3.0 -# Date: 2020-05-01 +# Version: 1.4.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # # Features: -# - Rewrite date format +# - Support for drafts # ### import logging import math -import os from pathlib import Path @@ -73,7 +72,7 @@ def footer_menu(self): return content - def data(self, page_index, posts_dir, total_posts): + def data(self, page_index, published_posts): self.__logger.debug('data - page_index: {0}'.format(page_index)) data = {} @@ -108,46 +107,45 @@ def data(self, page_index, posts_dir, total_posts): skip_entries = (int(page_index) - 1) * max_entries self.__logger.debug('data - skip_entries: {0}'.format(skip_entries)) - try: - for file in sorted(os.listdir(posts_dir), reverse=True): - count_entries += 1 + for entry in published_posts: + directory = entry['directory'] + file = entry['file'] + count_entries += 1 - # We count the entries, but for pages 2 and more, you don't show them - if skip_entries >= count_entries: - continue + # We count the entries, but for pages 2 and more, you don't show them + if skip_entries >= count_entries: + continue - post, _, post['content'] = Content().read_content(posts_dir, file) + post, _, post['content'] = Content().read_content(directory, file) - stem = Path(file).stem - post['url'] = stem - post['date'] = DateTimeSupport().rewrite_date(post['date']) + stem = Path(file).stem + post['url'] = stem + post['date'] = DateTimeSupport().rewrite_date(post['date']) - self.__logger.debug('data - post: {0}'.format(post)) + self.__logger.debug('data - post: {0}'.format(post)) - if page_index == 1: - if count_entries <= spotlight_entries: - self.__logger.debug('data - post added to spotlight_posts.') - data['spotlight_posts'].append(post) + if page_index == 1: + if count_entries <= spotlight_entries: + self.__logger.debug('data - post added to spotlight_posts.') + data['spotlight_posts'].append(post) - if spotlight_entries < count_entries <= (spotlight_entries + highlight_entries): - self.__logger.debug('data - post added to highlight_posts.') - data['highlight_posts'].append(post) + if spotlight_entries < count_entries <= (spotlight_entries + highlight_entries): + self.__logger.debug('data - post added to highlight_posts.') + data['highlight_posts'].append(post) - if count_entries > (spotlight_entries + highlight_entries): - self.__logger.debug('data - post added to (standard) posts.') - data['posts'].append(post) - - else: + if count_entries > (spotlight_entries + highlight_entries): self.__logger.debug('data - post added to (standard) posts.') data['posts'].append(post) - if count_entries == (max_entries + skip_entries): - self.__logger.debug('data - enough posts for this index page.') - break - except FileNotFoundError: - self.__logger.warning('COULD NOT FIND THE POSTS DIRECTORY {0}'.format(posts_dir)) - pass + else: + self.__logger.debug('data - post added to (standard) posts.') + data['posts'].append(post) + + if count_entries == (max_entries + skip_entries): + self.__logger.debug('data - enough posts for this index page.') + break + total_posts = len(published_posts) total_index_pages = math.ceil(total_posts / max_entries) self.__logger.debug('data - total_posts: {0}'.format(total_posts)) self.__logger.debug('data - total_index_pages: {0}'.format(total_index_pages)) @@ -165,6 +163,13 @@ def data(self, page_index, posts_dir, total_posts): ### # +# Version: 1.3.0 +# Date: 2020-05-01 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# - Rewrite date format +# # Version: 1.2.0 # Date: 2020-04-17 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/model/pages.py b/src/application/model/pages.py index 39db26f..ca876c4 100644 --- a/src/application/model/pages.py +++ b/src/application/model/pages.py @@ -6,6 +6,8 @@ # Date: 2020-05-08 # Author: Yves Vindevogel (vindevoy) # +# Features: +# - Support for drafts # Hotfix: # - Page with no tags returns a TypeError and not a KeyError # @@ -50,6 +52,29 @@ def files(self): return files + @property + def files_published(self): + directory = self.directory + files = [] + + for entry in self.files: + file = entry['file'] + meta, _, _ = Content().read_content(directory, file) # only need the meta data + + try: + value = meta['draft'] + draft = bool(value) + + except KeyError: + draft = False + + self.__logger.debug('published_files - {0}/{1} is a draft: {2}'.format(directory, file, draft)) + + if not draft: + files.append(entry) + + return files + @property def count(self): try: @@ -62,6 +87,13 @@ def count(self): return count + @property + def count_published(self): + count = len(self.files_published) + self.__logger.debug('count_published - count: {0}'.format(count)) + + return count + def data(self, page, skip_tags): self.__logger.debug('data - page: {0}'.format(page)) diff --git a/src/application/model/posts.py b/src/application/model/posts.py index 2d3bbb6..6cffc9f 100644 --- a/src/application/model/posts.py +++ b/src/application/model/posts.py @@ -51,17 +51,42 @@ def files(self): return files @property - def count(self): - try: - count = len(os.listdir(self.directory)) - except FileNotFoundError: - self.__logger.warning('COULD NOT FIND THE POSTS DIRECTORY {0}'.format(self.directory)) - count = 0 + def files_published(self): + directory = self.directory + files = [] + + for entry in self.files: + file = entry['file'] + meta, _, _ = Content().read_content(directory, file) # only need the meta data + + try: + value = meta['draft'] + draft = bool(value) + + except KeyError: + draft = False + + self.__logger.debug('published_files - {0}/{1} is a draft: {2}'.format(directory, file, draft)) + + if not draft: + files.append(entry) + return files + + @property + def count(self): + count = len(self.files) self.__logger.debug('count - count: {0}'.format(count)) return count + @property + def count_published(self): + count = len(self.files_published) + self.__logger.debug('count_published - count: {0}'.format(count)) + + return count + def data(self, post, skip_tags): self.__logger.debug('data - post: {0}'.format(post)) diff --git a/src/application/model/tags.py b/src/application/model/tags.py index 76effa3..2cc1d2f 100644 --- a/src/application/model/tags.py +++ b/src/application/model/tags.py @@ -2,19 +2,17 @@ # # Full history: see below # -# Version: 1.3.0 -# Date: 2020-05-01 +# Version: 1.4.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # # Changes: -# - Moved the tag_label and tag_text methods to a support class in common -# - Rewrite date format +# - Support for drafts # ### import logging import math -import os import string from operator import itemgetter @@ -47,8 +45,8 @@ def skip_tags(self): return tags - def list(self, posts_dir): - self.__logger.debug('list - posts_dir: {0}'.format(posts_dir)) + def list(self, posts): + self.__logger.debug('list - posts: {0}'.format(posts)) settings = Content().load_data_settings_yaml(self.__base_dir) self.__logger.debug('list - settings: {0}'.format(settings)) @@ -56,31 +54,30 @@ def list(self, posts_dir): # Starting with a dictionary as this is the easiest to find existing tags tags = {} - try: - for file in os.listdir(posts_dir): - meta, _, _ = Content().read_content(posts_dir, file) # No need to catch the content + for entry in posts: + directory = entry['directory'] + file = entry['file'] + + meta, _, _ = Content().read_content(directory, file) # No need to catch the content + + if meta['tags'] is None: + continue - if meta['tags'] is None: + for tag in meta['tags']: + label = TagsSupport().tag_label(tag) + + if label in settings['skip_tags']: + self.__logger.debug('list - tag {0} found in skip_tags'.format(tag)) continue - for tag in meta['tags']: - label = TagsSupport().tag_label(tag) - - if label in settings['skip_tags']: - self.__logger.debug('list - tag {0} found in skip_tags'.format(tag)) - continue - - if label in tags.keys(): - self.__logger.debug('list - tag {0} already exists, +1'.format(tag)) - current_count = tags[label]['count'] - tags[label]['count'] = current_count + 1 - else: - self.__logger.debug('list - tag {0} does not already exist'.format(tag)) - data = {'label': label, 'count': 1, 'text': string.capwords(tag)} - tags[label] = data - except FileNotFoundError: - self.__logger.warning('COULD NOT FIND THE POSTS DIRECTORY {0}'.format(posts_dir)) - pass + if label in tags.keys(): + self.__logger.debug('list - tag {0} already exists, +1'.format(tag)) + current_count = tags[label]['count'] + tags[label]['count'] = current_count + 1 + else: + self.__logger.debug('list - tag {0} does not already exist'.format(tag)) + data = {'label': label, 'count': 1, 'text': string.capwords(tag)} + tags[label] = data self.__logger.debug('list - tags: '.format(tags)) @@ -95,8 +92,8 @@ def list(self, posts_dir): return tags_list - def data(self, posts_dir, tag, page_index, index_max_posts, count_tag_posts): - self.__logger.debug('data - posts_dir: {0}'.format(posts_dir)) + def data(self, posts, tag, page_index, index_max_posts, count_tag_posts): + self.__logger.debug('data - posts: {0}'.format(posts)) self.__logger.debug('data - tag: {0}'.format(tag)) self.__logger.debug('data - page_index tags: {0}'.format(page_index)) self.__logger.debug('data - index_max_posts tags: {0}'.format(index_max_posts)) @@ -110,46 +107,46 @@ def data(self, posts_dir, tag, page_index, index_max_posts, count_tag_posts): self.__logger.debug('data - max_entries: {0}'.format(max_entries)) self.__logger.debug('data - skip_entries: {0}'.format(skip_entries)) - try: - for file in sorted(os.listdir(posts_dir), reverse=True): - post, _, post['content'] = Content().read_content(posts_dir, file) + for entry in posts: + directory = entry['directory'] + file = entry['file'] - if post['tags'] is None: - continue + post, _, post['content'] = Content().read_content(directory, file) - self.__logger.debug('data - post: {0}'.format(post)) + if post['tags'] is None: + continue - must_include = False + self.__logger.debug('data - post: {0}'.format(post)) - for tag_raw in post['tags']: - if TagsSupport().tag_label(tag_raw) == tag: - must_include = True - break + must_include = False - self.__logger.debug('data - must_include: {0}'.format(must_include)) + for tag_raw in post['tags']: + if TagsSupport().tag_label(tag_raw) == tag: + must_include = True + break - if must_include: - count_entries += 1 + self.__logger.debug('data - must_include: {0}'.format(must_include)) - # We count the entries, but for pages 2 and more, you don't show them - if skip_entries >= count_entries: - self.__logger.debug('data - post skipped}') - continue - else: - self.__logger.debug('data - post added') + if must_include: + count_entries += 1 + + # We count the entries, but for pages 2 and more, you don't show them + if skip_entries >= count_entries: + self.__logger.debug('data - post skipped}') + continue + else: + self.__logger.debug('data - post added') - stem = Path(file).stem - post['url'] = stem + stem = Path(file).stem + post['url'] = stem - post['date'] = DateTimeSupport().rewrite_date(post['date']) + post['date'] = DateTimeSupport().rewrite_date(post['date']) - data['posts'].append(post) + data['posts'].append(post) - if count_entries == (max_entries + skip_entries): - self.__logger.debug('data - enough posts') - break - except FileNotFoundError: - pass + if count_entries == (max_entries + skip_entries): + self.__logger.debug('data - enough posts') + break data['tag'] = {'name': TagsSupport().tag_text(tag), 'path': tag} @@ -162,26 +159,26 @@ def data(self, posts_dir, tag, page_index, index_max_posts, count_tag_posts): return data - def count_posts(self, posts_dir, tag): + def count_posts(self, posts, tag): self.__logger.debug('count_posts - tag: {0}'.format(tag)) - self.__logger.debug('count_posts - posts_dir: {0}'.format(posts_dir)) + self.__logger.debug('count_posts - posts: {0}'.format(posts)) count_entries = 0 - try: - for file in os.listdir(posts_dir): - post, _, _ = Content().read_content(posts_dir, file) + for entry in posts: + directory = entry['directory'] + file = entry['file'] - if post['tags'] is None: - continue + post, _, _ = Content().read_content(directory, file) + + if post['tags'] is None: + continue - for tag_raw in post['tags']: - if TagsSupport().tag_label(tag_raw) == tag: - count_entries += 1 - self.__logger.debug('count_posts - file {0} includes tag '.format(file)) - break - except FileNotFoundError: - pass + for tag_raw in post['tags']: + if TagsSupport().tag_label(tag_raw) == tag: + count_entries += 1 + self.__logger.debug('count_posts - file {0} includes tag '.format(file)) + break self.__logger.debug('count_posts - tag {0} has {1} posts'.format(tag, count_entries)) @@ -189,6 +186,14 @@ def count_posts(self, posts_dir, tag): ### # +# Version: 1.3.0 +# Date: 2020-05-01 +# Author: Yves Vindevogel (vindevoy) +# +# Changes: +# - Moved the tag_label and tag_text methods to a support class in common +# - Rewrite date format +# # Version: 1.2.1 # Date: 2020-04-23 # Author: Yves Vindevogel (vindevoy) diff --git a/src/data/environment/localhost.yml b/src/data/environment/localhost.yml index 34a2cbc..7d7bfeb 100644 --- a/src/data/environment/localhost.yml +++ b/src/data/environment/localhost.yml @@ -2,6 +2,7 @@ content: meta_content_separator: "----------" + include_drafts: False directories: theme: diff --git a/src/data/posts/0013_version_1_5_1.md b/src/data/posts/0013_version_1_5_1.md new file mode 100644 index 0000000..9efa942 --- /dev/null +++ b/src/data/posts/0013_version_1_5_1.md @@ -0,0 +1,36 @@ +--- + +title: "Release v1.5.1" + +author: "Yves Vindevogel" +date: "2020-05-07" + +image: "cherry3.jpg" + +summary: "Releasing a minor bug update" + +draft: True + +tags: + - History + - Bug fixes + +---------- + +This is a minor bug update, just one small bug, sorry. + + +## Release info + +- author: Yves Vindevogel (vindevoy) +- date: 2020-05-07 + +## Bug Fixes + +- There was a problem with the search results. The font weight (bold) of found text in the search results is now case-insensitive. + +### Github + +For more information on this release, see the issues for this milestone: + +- [https://github.com/vindevoy/cherryblog/milestone/14](https://github.com/vindevoy/cherryblog/milestone/14) \ No newline at end of file From 50f541d0a082bcf11b91f550fd7dca9fe7bc517d Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 19:21:11 +0200 Subject: [PATCH 13/21] Added announcement v1.5.1 --- src/data/environment/localhost.yml | 2 +- src/data/posts/0013_version_1_5_1.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/environment/localhost.yml b/src/data/environment/localhost.yml index 7d7bfeb..183e49d 100644 --- a/src/data/environment/localhost.yml +++ b/src/data/environment/localhost.yml @@ -2,7 +2,7 @@ content: meta_content_separator: "----------" - include_drafts: False + include_drafts: True directories: theme: diff --git a/src/data/posts/0013_version_1_5_1.md b/src/data/posts/0013_version_1_5_1.md index 9efa942..25e0ceb 100644 --- a/src/data/posts/0013_version_1_5_1.md +++ b/src/data/posts/0013_version_1_5_1.md @@ -9,7 +9,7 @@ image: "cherry3.jpg" summary: "Releasing a minor bug update" -draft: True +draft: False tags: - History From dce23e4e9c9c4d9786152c586dd90611afb2e237 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 19:47:40 +0200 Subject: [PATCH 14/21] New version in widget --- src/data/codeversion/settings.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/codeversion/settings.yml b/src/data/codeversion/settings.yml index 707d8c5..31940a4 100644 --- a/src/data/codeversion/settings.yml +++ b/src/data/codeversion/settings.yml @@ -1,5 +1,5 @@ --- text: - - 'Production: v.1.5.0 (master branch)' - - 'Next version: v.1.5.1 (develop branch)' \ No newline at end of file + - 'Production: v.1.5.1 (master branch)' + - 'Next version: v.1.6.0 (develop branch)' \ No newline at end of file From d0ab439d2df6fa31c8bb6707af805fe18066c5af Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 19:47:56 +0200 Subject: [PATCH 15/21] Issue-37: Added html minify --- Makefile | 19 +++++++--- src/application/controller/application.py | 45 +++++++++++++++-------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index ca60ab3..841a83a 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,11 @@ ### # -# Version: 1.2.1 -# Date: 2020-04-25 +# Version: 1.3.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # -# Fixes: -# - all logging is now in application.log instead of ENVIRONMENT.log (settings determine it for the run) -# - better history generation +# Features: +# - dependency for django-htmlmin # ### @@ -59,6 +58,8 @@ dependencies: @pip3 install jinja2 @pip3 install pyyaml @pip3 install markdown + @pip3 install django-htmlmin + @echo '[OK] Dependencies in Python installed' @@ -113,6 +114,14 @@ stop: ### # +# Version: 1.2.1 +# Date: 2020-04-25 +# Author: Yves Vindevogel (vindevoy) +# +# Fixes: +# - all logging is now in application.log instead of ENVIRONMENT.log (settings determine it for the run) +# - better history generation +# # Version: 1.2.0 # Date: 2020-04-11 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/controller/application.py b/src/application/controller/application.py index 686c6b8..1b5aa11 100644 --- a/src/application/controller/application.py +++ b/src/application/controller/application.py @@ -2,15 +2,17 @@ # # Full history: see below # -# Version: 2.3.0 -# Date: 2020-04-26 +# Version: 2.4.0 +# Date: 2020-05-07 # Author: Yves Vindevogel (vindevoy) # -# Caching enabled or not +# Using HTML minify # ### import cherrypy +from htmlmin.minify import html_minify + import logging from datetime import datetime @@ -35,7 +37,7 @@ def index(self, page_index=1, **_): start = datetime.now() if Options().caching and PageCacher().cached_already(request): - rendered = PageCacher().get_cached(request) + minified = PageCacher().get_cached(request) else: data = DataLoader().index_data(page_index) @@ -43,14 +45,15 @@ def index(self, page_index=1, **_): template = TemplateLoader().get_template('screen_index.html') rendered = template.render(data=data) + minified = html_minify(rendered) if Options().caching: - PageCacher().cache(request, rendered) + PageCacher().cache(request, minified) finished = datetime.now() self.__logger.info('{0} {1}'.format(request, finished - start)) - return rendered + return minified @cherrypy.expose def pages(self, page, **_): @@ -58,7 +61,7 @@ def pages(self, page, **_): start = datetime.now() if Options().caching and PageCacher().cached_already(request): - rendered = PageCacher().get_cached(request) + minified = PageCacher().get_cached(request) else: # page on the URL: http://www.yoursite.ext/pages/page @@ -67,14 +70,15 @@ def pages(self, page, **_): template = TemplateLoader().get_template('screen_page.html') rendered = template.render(data=data) + minified = html_minify(rendered) if Options().caching: - PageCacher().cache(request, rendered) + PageCacher().cache(request, minified) finished = datetime.now() self.__logger.info('{0} {1}'.format(request, finished - start)) - return rendered + return minified @cherrypy.expose def posts(self, post, **_): @@ -82,7 +86,7 @@ def posts(self, post, **_): start = datetime.now() if Options().caching and PageCacher().cached_already(request): - rendered = PageCacher().get_cached(request) + minified = PageCacher().get_cached(request) else: data = DataLoader().posts_data(post) @@ -90,14 +94,15 @@ def posts(self, post, **_): template = TemplateLoader().get_template('screen_post.html') rendered = template.render(data=data) + minified = html_minify(rendered) if Options().caching: - PageCacher().cache(request, rendered) + PageCacher().cache(request, minified) finished = datetime.now() self.__logger.info('{0} {1}'.format(request, finished - start)) - return rendered + return minified @cherrypy.expose def tags(self, tag, page_index=1, **_): @@ -105,7 +110,7 @@ def tags(self, tag, page_index=1, **_): start = datetime.now() if Options().caching and PageCacher().cached_already(request): - rendered = PageCacher().get_cached(request) + minified = PageCacher().get_cached(request) else: data = DataLoader().tags_data(tag, page_index) @@ -113,14 +118,15 @@ def tags(self, tag, page_index=1, **_): template = TemplateLoader().get_template('screen_tag.html') rendered = template.render(data=data) + minified = html_minify(rendered) if Options().caching: - PageCacher().cache(request, rendered) + PageCacher().cache(request, minified) finished = datetime.now() self.__logger.info('{0} {1}'.format(request, finished - start)) - return rendered + return minified @cherrypy.expose def search(self, page_index=1, query='', **_): @@ -132,11 +138,12 @@ def search(self, page_index=1, query='', **_): template = TemplateLoader().get_template('screen_search.html') rendered = template.render(data=data) + minified = html_minify(rendered) finished = datetime.now() self.__logger.info('{0} {1}'.format(request, finished - start)) - return rendered + return minified # @cherrypy.expose # def print_page(self, page, **_): @@ -160,6 +167,12 @@ def search(self, page_index=1, query='', **_): ### # +# Version: 2.3.0 +# Date: 2020-04-26 +# Author: Yves Vindevogel (vindevoy) +# +# Caching enabled or not +# # Version: 2.2.0 # Date: 2020-04-22 # Author: Yves Vindevogel (vindevoy) From eaef60ed15d3aa60c5d502cb7ea696c593e041ad Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Thu, 7 May 2020 21:16:26 +0200 Subject: [PATCH 16/21] Issue-111: Google sitemap --- .gitignore | 3 +- Makefile | 15 +++- src/application/controller/application.py | 3 +- src/application/sitemap.py | 98 +++++++++++++++++++++++ src/data/environment/localhost.yml | 4 + src/data/environment/production.sample | 5 ++ 6 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 src/application/sitemap.py diff --git a/.gitignore b/.gitignore index d8c0f77..d1027f6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ tmp/ download/ log/ -production.yml \ No newline at end of file +production.yml +sitemap.xml \ No newline at end of file diff --git a/Makefile b/Makefile index 841a83a..3c75365 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ # # Features: # - dependency for django-htmlmin +# - create sitemap.xml # ### @@ -100,11 +101,21 @@ history: @echo '[OK] history copied to pages' -develop: +sitemap: + @mkdir -p ./src/data/sitemap + @python3 ./src/application/sitemap.py + + + @echo '[OK] sitemap.xml created' + +google: sitemap + @curl http://www.google.com/ping?sitemap=https://cherryblog.org/sitemap.xml > /dev/null + +develop: sitemap @mkdir -p ./log @python3 ./src/application/main.py 2>&1 | tee ./log/application.log -production: +production: sitemap @mkdir -p /var/log/cherryblog @python3 ./src/application/main.py --env production 2>&1 | tee /var/log/cherryblog/application.log & diff --git a/src/application/controller/application.py b/src/application/controller/application.py index 1b5aa11..0340713 100644 --- a/src/application/controller/application.py +++ b/src/application/controller/application.py @@ -11,11 +11,10 @@ ### import cherrypy -from htmlmin.minify import html_minify - import logging from datetime import datetime +from htmlmin.minify import html_minify from common.options import Options from common.singleton import Singleton diff --git a/src/application/sitemap.py b/src/application/sitemap.py new file mode 100644 index 0000000..2c39f78 --- /dev/null +++ b/src/application/sitemap.py @@ -0,0 +1,98 @@ +### +# +# Full history: see below +# +# Version: 1.0.0 +# Date: 2020-05-07 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# - Build a sitemap +# +### + +import logging +import os + +from pathlib import Path + +from common.options import Options +from common.content import Content +from controller.data_loader import DataLoader +from controller.logging_loader import LoggingLoader +from controller.settings_loader import SettingsLoader + +environment = 'localhost' +data_dir = os.path.join(os.getcwd(), 'src', 'data') + +Options().environment = environment +Options().data_dir = data_dir + +settings = SettingsLoader(environment).parse() + +LoggingLoader().configure() + +logger = logging.getLogger('SITEMAP') + +# Override the drafts because Google will never find them in production most likely +Options().include_drafts = False + +xml = '\n' +xml += '\n' + +priority = 1.0 + +page_priorities = {'about': {'priority': 1.0, 'update': 'monthly'}, + 'documentation': {'priority': 0.9, 'update': 'monthly'}, + 'credits': {'priority': 0.1, 'update': 'yearly'} + } + +for entry in DataLoader().posts_published: + file = entry['file'] + stem = Path(file).stem + + logger.info('Parsing {0}'.format(file)) + + meta, _, _ = Content().read_content('posts', file) + + xml += ' \n' + xml += ' https://cherryblog.org/posts/{0}\n'.format(stem) + xml += ' {0}\n'.format(meta['date']) + xml += ' never\n' + xml += ' {0}\n'.format(round(priority, 2)) + xml += ' \n' + + if priority > 0.5: + priority = round(priority - 0.1, 2) + +for entry in DataLoader().pages_published: + file = entry['file'] + stem = Path(file).stem + + logger.info('Parsing {0}'.format(file)) + + meta, _, _ = Content().read_content('pages', file) + + try: + priority = page_priorities[stem]['priority'] + except KeyError: + priority = 0.5 + + try: + update = page_priorities[stem]['update'] + except KeyError: + update = 'monthly' + + xml += ' \n' + xml += ' https://cherryblog.org/pages/{0}\n'.format(stem) + xml += ' {0}\n'.format(meta['date']) + xml += ' {0}\n'.format(update) + xml += ' {0}\n'.format(round(priority, 2)) + xml += ' \n' + +xml += '\n' + + +sitemap_file = open(os.path.join(data_dir, 'sitemap', 'sitemap.xml'), 'w') +sitemap_file.write(xml) +sitemap_file.close() diff --git a/src/data/environment/localhost.yml b/src/data/environment/localhost.yml index 183e49d..d29e905 100644 --- a/src/data/environment/localhost.yml +++ b/src/data/environment/localhost.yml @@ -35,6 +35,10 @@ tools: - url: '/static' absolute: False path: 'src/theme/default/static' + staticfiles: + - url: '/sitemap.xml' + absolute: False + path: 'src/data/sitemap/sitemap.xml' user: privileges: False diff --git a/src/data/environment/production.sample b/src/data/environment/production.sample index c200b70..f1da96e 100644 --- a/src/data/environment/production.sample +++ b/src/data/environment/production.sample @@ -2,6 +2,7 @@ content: meta_content_separator: "----------" + include_drafts: False directories: theme: @@ -34,6 +35,10 @@ tools: - url: '/static' absolute: False path: 'src/theme/default/static' + staticfiles: + - url: '/sitemap.xml' + absolute: False + path: 'src/data/sitemap/sitemap.xml' user: privileges: True From 07c196724377bda63564aa4279d590bddeb40104 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Fri, 8 May 2020 15:33:24 +0200 Subject: [PATCH 17/21] Applying stash --- src/application/controller/remapper.py | 50 +++++++++++++++++++++++ src/application/model/mapping.py | 56 ++++++++++++++++++++++++++ src/data/mapping/settings.yml | 7 ++++ 3 files changed, 113 insertions(+) create mode 100644 src/application/controller/remapper.py create mode 100644 src/application/model/mapping.py create mode 100644 src/data/mapping/settings.yml diff --git a/src/application/controller/remapper.py b/src/application/controller/remapper.py new file mode 100644 index 0000000..eaa3d64 --- /dev/null +++ b/src/application/controller/remapper.py @@ -0,0 +1,50 @@ +### +# +# Version: 1.0.0 +# Date: 2020-05-08 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# Remapping of incoming requests to content documents +# Remapping of content to outgoing URLs +# +### + +import logging + +from common.options import Options +from common.singleton import Singleton + + +class Remapper(metaclass=Singleton): + outgoing_content = None + incoming_content = None + + __logger = None + + def __init__(self): + self.__logger = logging.getLogger('REMAPPER') + self.__logger.setLevel(Options().default_logging_level) + + def remap_document(self, doc): + self.__logger.debug('remap_document - doc: {0}'.format(doc)) + + return self.__remap(doc, self.outgoing_content, 'OUT') + + def remap_url(self, url): + self.__logger.debug('remap_url - url: {0}'.format(url)) + + return self.__remap(url, self.incoming_content, 'IN') + + def __remap(self, mapping, mappings, way): + self.__logger.debug('__remap - mapping: {0}'.format(mapping)) + self.__logger.debug('__remap - mappings: {0}'.format(mappings)) + + if mapping in mappings: + mapped = mappings[mapping] + self.__logger.debug('__remap - mapped: {0}'.format(mapped)) + + self.__logger.info('{0}: {1} -> {2}'.format(way, mapping, mapped)) + return mapped + else: + return mapping diff --git a/src/application/model/mapping.py b/src/application/model/mapping.py new file mode 100644 index 0000000..6d7f6d1 --- /dev/null +++ b/src/application/model/mapping.py @@ -0,0 +1,56 @@ +### +# +# Full history: see below +# +# Version: 1.0.0 +# Date: 2020-05-07 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# - Mapping of URLs to physical files +# +### + +import logging + +from common.options import Options +from common.content import Content +from common.singleton import Singleton + + +class Mapping(metaclass=Singleton): + __base_dir = 'mapping' + __logger = None + + incoming = None + outgoing = None + + def __init__(self): + self.__logger = logging.getLogger('MODEL.MAPPING') + self.__logger.setLevel(Options().default_logging_level) + + self.__data() + + def __data(self): + content = Content().load_data_settings_yaml(self.__base_dir) + self.__logger.debug('__data - content: {0}'.format(content)) + + incoming = {} + outgoing = {} + + for mapping in content['content']: + self.__logger.debug('__data - mapping: {0}'.format(mapping)) + + target = mapping['target'] + source = mapping['source'] + self.__logger.debug('__data - target: {0}'.format(target)) + self.__logger.debug('__data - source: {0}'.format(source)) + + incoming[target] = source + self.__logger.info('mapping incoming URL \'{0}\' to source \'{1}\''.format(target, source)) + + outgoing[source] = target + self.__logger.info('mapping outgoing source \'{0}\' to URL \'{1}\''.format(source, target)) + + self.incoming = incoming + self.outgoing = outgoing diff --git a/src/data/mapping/settings.yml b/src/data/mapping/settings.yml new file mode 100644 index 0000000..8af32ef --- /dev/null +++ b/src/data/mapping/settings.yml @@ -0,0 +1,7 @@ +--- + +content: + - target: 'posts/announcement' + source: 'posts/0001_announcement' + - target: 'posts/version_1.0.0' + source: 'posts/0002_version_1_0_0' From a52a1e3b5e57759e7cbe3ea9ef39146f378da869 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Fri, 8 May 2020 15:34:05 +0200 Subject: [PATCH 18/21] From stash --- src/application/controller/application.py | 11 ++++++++++- src/application/controller/data_loader.py | 8 ++++++++ src/application/main.py | 5 +++++ src/application/model/index.py | 6 +++++- src/theme/default/elements/_html/highlight_post.html | 2 +- src/theme/default/elements/_html/spotlight_post.html | 2 +- src/theme/default/elements/_html/standard_post.html | 2 +- 7 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/application/controller/application.py b/src/application/controller/application.py index 0340713..a898930 100644 --- a/src/application/controller/application.py +++ b/src/application/controller/application.py @@ -20,6 +20,7 @@ from common.singleton import Singleton from controller.data_loader import DataLoader from controller.page_cacher import PageCacher +from controller.remapper import Remapper from view.templateloader import TemplateLoader @@ -81,13 +82,21 @@ def pages(self, page, **_): @cherrypy.expose def posts(self, post, **_): - request = '/posts/{0}'.format(post) start = datetime.now() + request = 'posts/{0}'.format(post) + self.__logger.info('posts - request: {0}'.format(request)) if Options().caching and PageCacher().cached_already(request): minified = PageCacher().get_cached(request) else: + remapped = Remapper().remap_url(request) + self.__logger.info('posts - remapped: {0}'.format(remapped)) + + if request != remapped: + post = remapped.split('/')[1] + self.__logger.info('posts - post: {0}'.format(post)) + data = DataLoader().posts_data(post) data['url'] = request diff --git a/src/application/controller/data_loader.py b/src/application/controller/data_loader.py index e91912b..36d5c5b 100644 --- a/src/application/controller/data_loader.py +++ b/src/application/controller/data_loader.py @@ -20,6 +20,7 @@ from model.i8n import I8N from model.important_news import ImportantNews from model.index import Index +from model.mapping import Mapping from model.pages import Pages from model.posts import Posts from model.search import Search @@ -139,6 +140,13 @@ def index_spotlight_posts(self): def index_highlight_posts(self): return self.__get_data('index_highlight_posts', Index(), 'highlight_posts') + # mapping + def mapping_incoming(self): + return self.__get_data('mapping_incoming', Mapping(), 'incoming') + + def mapping_outgoing(self): + return self.__get_data('mapping_outgoing', Mapping(), 'outgoing') + # pages @property def pages_directory(self): diff --git a/src/application/main.py b/src/application/main.py index ca63f27..421da0c 100644 --- a/src/application/main.py +++ b/src/application/main.py @@ -25,6 +25,7 @@ from controller.application import Application from controller.data_loader import DataLoader from controller.logging_loader import LoggingLoader +from controller.remapper import Remapper from controller.settings_loader import SettingsLoader __application = 'CherryBlog' @@ -78,6 +79,10 @@ logger.info('Default date input format set to \'{0}\'.'.format(DateTimeSupport().input_format)) logger.info('Default date output format set to \'{0}\'.'.format(DateTimeSupport().output_format)) + # Loading the remapping + Remapper().outgoing_content = DataLoader().mapping_outgoing() + Remapper().incoming_content = DataLoader().mapping_incoming() + if Options().use_ssl: # vindevoy - 2020-04-25 # You must use the builtin SSL option. If you use pyOpenSLL you get the error below (see history) diff --git a/src/application/model/index.py b/src/application/model/index.py index b03d832..2f3e5af 100644 --- a/src/application/model/index.py +++ b/src/application/model/index.py @@ -20,6 +20,7 @@ from common.datetime_support import DateTimeSupport from common.options import Options from common.singleton import Singleton +from controller.remapper import Remapper class Index(metaclass=Singleton): @@ -119,7 +120,10 @@ def data(self, page_index, published_posts): post, _, post['content'] = Content().read_content(directory, file) stem = Path(file).stem - post['url'] = stem + url = 'posts/{0}'.format(stem) + url = Remapper().remap_document(url) + + post['url'] = url post['date'] = DateTimeSupport().rewrite_date(post['date']) self.__logger.debug('data - post: {0}'.format(post)) diff --git a/src/theme/default/elements/_html/highlight_post.html b/src/theme/default/elements/_html/highlight_post.html index 77a747d..eaedd7b 100644 --- a/src/theme/default/elements/_html/highlight_post.html +++ b/src/theme/default/elements/_html/highlight_post.html @@ -18,7 +18,7 @@ {% with author = post.author, date = post.date %} diff --git a/src/theme/default/elements/_html/spotlight_post.html b/src/theme/default/elements/_html/spotlight_post.html index 179e479..9a20bb3 100644 --- a/src/theme/default/elements/_html/spotlight_post.html +++ b/src/theme/default/elements/_html/spotlight_post.html @@ -18,7 +18,7 @@ {% with author = post.author, date = post.date %} diff --git a/src/theme/default/elements/_html/standard_post.html b/src/theme/default/elements/_html/standard_post.html index 2eae580..be86068 100644 --- a/src/theme/default/elements/_html/standard_post.html +++ b/src/theme/default/elements/_html/standard_post.html @@ -16,7 +16,7 @@ {% with author = post.author, date = post.date %} From e31dee489efa3ef7ec74d44e5d262f69947b7806 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Fri, 8 May 2020 17:22:41 +0200 Subject: [PATCH 19/21] Issue-114: Decouple URL from document --- src/application/controller/application.py | 63 ++++++++++++++----- src/application/controller/data_loader.py | 4 +- src/application/controller/remapper.py | 4 +- src/application/model/index.py | 5 +- src/application/model/mapping.py | 9 ++- src/application/model/pages.py | 11 +++- src/application/model/posts.py | 22 +++---- src/application/model/search.py | 35 +++++++---- src/application/model/tags.py | 18 +++++- src/data/environment/localhost.yml | 2 +- src/data/main_menu/settings.yml | 2 +- src/data/posts/0013_version_1_5_1.md | 2 +- src/data/posts/0014_version_1_5_2.md | 35 +++++++++++ .../elements/_html/highlight_post.html | 17 +++-- .../elements/_html/spotlight_post.html | 17 +++-- .../default/elements/_html/standard_post.html | 17 +++-- 16 files changed, 197 insertions(+), 66 deletions(-) create mode 100644 src/data/posts/0014_version_1_5_2.md diff --git a/src/application/controller/application.py b/src/application/controller/application.py index a898930..080a5de 100644 --- a/src/application/controller/application.py +++ b/src/application/controller/application.py @@ -2,11 +2,12 @@ # # Full history: see below # -# Version: 2.4.0 -# Date: 2020-05-07 +# Version: 2.5.0 +# Date: 2020-05-08 # Author: Yves Vindevogel (vindevoy) # -# Using HTML minify +# Features: +# - Remapping of URLs to documents # ### @@ -33,9 +34,10 @@ def __init__(self): @cherrypy.expose def index(self, page_index=1, **_): - request = '/index/{0}'.format(page_index) start = datetime.now() + request = '/index/{0}'.format(page_index) + if Options().caching and PageCacher().cached_already(request): minified = PageCacher().get_cached(request) @@ -57,16 +59,25 @@ def index(self, page_index=1, **_): @cherrypy.expose def pages(self, page, **_): - request = '/pages/{0}'.format(page) start = datetime.now() + request = '/pages/{0}'.format(page) + self.__logger.debug('pages - request: {0}'.format(request)) + if Options().caching and PageCacher().cached_already(request): minified = PageCacher().get_cached(request) else: + remapped = Remapper().remap_url(request) + self.__logger.debug('pages - remapped: {0}'.format(remapped)) + + if request != remapped: + page = remapped.split('/')[2] + self.__logger.debug('pages - page: {0}'.format(page)) + # page on the URL: http://www.yoursite.ext/pages/page data = DataLoader().pages_data(page) - data['url'] = request + data['url'] = remapped template = TemplateLoader().get_template('screen_page.html') rendered = template.render(data=data) @@ -83,22 +94,23 @@ def pages(self, page, **_): @cherrypy.expose def posts(self, post, **_): start = datetime.now() - request = 'posts/{0}'.format(post) - self.__logger.info('posts - request: {0}'.format(request)) + + request = '/posts/{0}'.format(post) + self.__logger.debug('posts - request: {0}'.format(request)) if Options().caching and PageCacher().cached_already(request): minified = PageCacher().get_cached(request) else: remapped = Remapper().remap_url(request) - self.__logger.info('posts - remapped: {0}'.format(remapped)) + self.__logger.debug('posts - remapped: {0}'.format(remapped)) if request != remapped: - post = remapped.split('/')[1] - self.__logger.info('posts - post: {0}'.format(post)) + post = remapped.split('/')[2] + self.__logger.debug('posts - post: {0}'.format(post)) data = DataLoader().posts_data(post) - data['url'] = request + data['url'] = remapped template = TemplateLoader().get_template('screen_post.html') rendered = template.render(data=data) @@ -114,15 +126,27 @@ def posts(self, post, **_): @cherrypy.expose def tags(self, tag, page_index=1, **_): - request = '/tags/{0}/{1}'.format(tag, page_index) start = datetime.now() + request = '/tags/{0}/{1}'.format(tag, page_index) + self.__logger.debug('tags - tag: {0}'.format(tag)) + if Options().caching and PageCacher().cached_already(request): minified = PageCacher().get_cached(request) else: + short_request = 'tags/{0}'.format(tag) + self.__logger.debug('tags - short_request: {0}'.format(short_request)) + + remapped = Remapper().remap_url(short_request) + self.__logger.debug('tags - remapped: {0}'.format(remapped)) + + if short_request != remapped: + tag = remapped.split('/')[2] + self.__logger.debug('tags - tag: {0}'.format(tag)) + data = DataLoader().tags_data(tag, page_index) - data['url'] = request + data['url'] = remapped template = TemplateLoader().get_template('screen_tag.html') rendered = template.render(data=data) @@ -137,10 +161,11 @@ def tags(self, tag, page_index=1, **_): return minified @cherrypy.expose - def search(self, page_index=1, query='', **_): - request = '/search/{0}/{1}'.format(page_index, query) + def search(self, query='', page_index=1, **_): start = datetime.now() + request = '/search/{0}/{1}'.format(query, page_index) + data = DataLoader().search_data(query, page_index) data['url'] = request @@ -175,6 +200,12 @@ def search(self, page_index=1, query='', **_): ### # +# Version: 2.4.0 +# Date: 2020-05-07 +# Author: Yves Vindevogel (vindevoy) +# +# Using HTML minify +# # Version: 2.3.0 # Date: 2020-04-26 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/controller/data_loader.py b/src/application/controller/data_loader.py index 36d5c5b..f3780e4 100644 --- a/src/application/controller/data_loader.py +++ b/src/application/controller/data_loader.py @@ -3,11 +3,12 @@ # Full history: see below # # Version: 1.4.0 -# Date: 2020-05-07 +# Date: 2020-05-08 # Author: Yves Vindevogel (vindevoy) # # Features: # - Support for drafts +# - Remapping of URLs to documents # ### @@ -76,6 +77,7 @@ def common_data(self): 'settings': self.global_settings, 'tags_list': self.tags_list, 'tags_list_count': self.tags_list_count, + 'tags_skip_list': self.tags_skip_list, 'main_menu': self.index_main_menu, 'footer_menu': self.index_footer_menu, 'important_news': self.important_news_data, diff --git a/src/application/controller/remapper.py b/src/application/controller/remapper.py index eaa3d64..415f698 100644 --- a/src/application/controller/remapper.py +++ b/src/application/controller/remapper.py @@ -42,9 +42,7 @@ def __remap(self, mapping, mappings, way): if mapping in mappings: mapped = mappings[mapping] - self.__logger.debug('__remap - mapped: {0}'.format(mapped)) - - self.__logger.info('{0}: {1} -> {2}'.format(way, mapping, mapped)) + self.__logger.debug('{0}: {1} -> {2}'.format(way, mapping, mapped)) return mapped else: return mapping diff --git a/src/application/model/index.py b/src/application/model/index.py index 2f3e5af..717bce3 100644 --- a/src/application/model/index.py +++ b/src/application/model/index.py @@ -3,11 +3,12 @@ # Full history: see below # # Version: 1.4.0 -# Date: 2020-05-07 +# Date: 2020-05-08 # Author: Yves Vindevogel (vindevoy) # # Features: # - Support for drafts +# - Remapping of URLs to documents # ### @@ -120,7 +121,7 @@ def data(self, page_index, published_posts): post, _, post['content'] = Content().read_content(directory, file) stem = Path(file).stem - url = 'posts/{0}'.format(stem) + url = '/posts/{0}'.format(stem) url = Remapper().remap_document(url) post['url'] = url diff --git a/src/application/model/mapping.py b/src/application/model/mapping.py index 6d7f6d1..b78650f 100644 --- a/src/application/model/mapping.py +++ b/src/application/model/mapping.py @@ -3,7 +3,7 @@ # Full history: see below # # Version: 1.0.0 -# Date: 2020-05-07 +# Date: 2020-05-08 # Author: Yves Vindevogel (vindevoy) # # Features: @@ -43,6 +43,13 @@ def __data(self): target = mapping['target'] source = mapping['source'] + + if target[0:1] != '/': + target = '/{0}'.format(target) + + if source[0:1] != '/': + source = '/{0}'.format(source) + self.__logger.debug('__data - target: {0}'.format(target)) self.__logger.debug('__data - source: {0}'.format(source)) diff --git a/src/application/model/pages.py b/src/application/model/pages.py index ca876c4..530af3d 100644 --- a/src/application/model/pages.py +++ b/src/application/model/pages.py @@ -2,14 +2,12 @@ # # Full history: see below # -# Version: 1.3.1 +# Version: 1.4.0 # Date: 2020-05-08 # Author: Yves Vindevogel (vindevoy) # # Features: # - Support for drafts -# Hotfix: -# - Page with no tags returns a TypeError and not a KeyError # ### @@ -133,6 +131,13 @@ def data(self, page, skip_tags): ### # +# Version: 1.3.1 +# Date: 2020-05-08 +# Author: Yves Vindevogel (vindevoy) +# +# Hotfix: +# - Page with no tags returns a TypeError and not a KeyError +# # Version: 1.3.0 # Date: 2020-05-01 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/model/posts.py b/src/application/model/posts.py index 634b33c..af80845 100644 --- a/src/application/model/posts.py +++ b/src/application/model/posts.py @@ -2,12 +2,12 @@ # # Full history: see below # -# Version: 1.3.1 +# Version: 1.4.0 # Date: 2020-05-08 # Author: Yves Vindevogel (vindevoy) # -# Hotfix: -# - Page with no tags returns a TypeError and not a KeyError +# Feature: +# - Support for drafts # ### @@ -70,15 +70,9 @@ def files_published(self): if not draft: files.append(entry) -<<<<<<< HEAD return files -======= - - return files - ->>>>>>> v1.6.0 @property def count(self): count = len(self.files) @@ -113,11 +107,8 @@ def data(self, post, skip_tags): else: self.__logger.debug('data - removing skipped tag: {0}'.format(tag)) except TypeError: -<<<<<<< HEAD pass except KeyError: -======= ->>>>>>> v1.6.0 pass data['post']['tags'] = tags @@ -135,6 +126,13 @@ def data(self, post, skip_tags): ### # +# Version: 1.3.1 +# Date: 2020-05-08 +# Author: Yves Vindevogel (vindevoy) +# +# Hotfix: +# - Page with no tags returns a TypeError and not a KeyError +# # Version: 1.3.0 # Date: 2020-05-01 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/model/search.py b/src/application/model/search.py index 0cc1173..b287625 100644 --- a/src/application/model/search.py +++ b/src/application/model/search.py @@ -2,12 +2,13 @@ # # Full history: see below # -# Version: 1.1.1 -# Date: 2020-05-06 +# Version: 1.2.0 +# Date: 2020-05-08 # Author: Yves Vindevogel (vindevoy) # # Fixes: -# - The replace with the bold tags works, but it does not capture capital letters. Introducing another method. +# - Support for drafts +# - Remapping of URLs to documents # ### @@ -21,6 +22,7 @@ from common.singleton import Singleton from controller.data_cacher import DataCacher +from controller.remapper import Remapper class Search(metaclass=Singleton): @@ -56,24 +58,28 @@ def data(self, query, page_index, search_base, max_entries): file = item['file'] stem = Path(file).stem + unmapped = '/{0}/{1}'.format(directory, stem) + remapped = Remapper().remap_document(unmapped) + + if unmapped != remapped: + stem = remapped.split('/')[2] + # adding the stem to the object for the final url item['stem'] = stem - url = '/{0}/{1}'.format(directory, stem) - - if url in excluded: + if remapped in excluded: self.__logger.debug('data - excluded item: {0}'.format(item)) continue - cached_already = DataCacher().cached_already(url) + cached_already = DataCacher().cached_already(unmapped) if cached_already: - self.__logger.debug('data - cached: {0}'.format(url)) + self.__logger.debug('data - cached: {0}'.format(unmapped)) - meta = DataCacher().get_cached('{0}/meta'.format(url)) - content = DataCacher().get_cached('{0}/content'.format(url)) + meta = DataCacher().get_cached('{0}/meta'.format(unmapped)) + content = DataCacher().get_cached('{0}/content'.format(unmapped)) else: - self.__logger.debug('data - not cached: {0}'.format(url)) + self.__logger.debug('data - not cached: {0}'.format(unmapped)) meta, content, _ = Content().read_content(directory, file) @@ -178,6 +184,13 @@ def data(self, query, page_index, search_base, max_entries): ### # +# Version: 1.1.1 +# Date: 2020-05-06 +# Author: Yves Vindevogel (vindevoy) +# +# Fixes: +# - The replace with the bold tags works, but it does not capture capital letters. Introducing another method. +# # Version: 1.1.0 # Date: 2020-05-01 # Author: Yves Vindevogel (vindevoy) diff --git a/src/application/model/tags.py b/src/application/model/tags.py index 2cc1d2f..f2cddda 100644 --- a/src/application/model/tags.py +++ b/src/application/model/tags.py @@ -3,11 +3,12 @@ # Full history: see below # # Version: 1.4.0 -# Date: 2020-05-07 +# Date: 2020-05-08 # Author: Yves Vindevogel (vindevoy) # # Changes: # - Support for drafts +# - Remapping of URLs to documents # ### @@ -23,6 +24,7 @@ from common.options import Options from common.singleton import Singleton from common.tags_support import TagsSupport +from controller.remapper import Remapper class Tags(metaclass=Singleton): @@ -87,6 +89,16 @@ def list(self, posts): for _, value in tags.items(): # Only need the value tags_array.append(value) + for tag in tags_array: + label = tag['label'] + unmapped = '/tags/{0}'.format(label) + remapped = Remapper().remap_document(unmapped) + + if unmapped != remapped: + label = remapped.split('/')[2] + tag['label'] = label + tag['text'] = TagsSupport().tag_text(label) + tags_list = sorted(tags_array, key=itemgetter('count'), reverse=True) self.__logger.debug('list - sorted tags: '.format(tags_list)) @@ -138,8 +150,10 @@ def data(self, posts, tag, page_index, index_max_posts, count_tag_posts): self.__logger.debug('data - post added') stem = Path(file).stem - post['url'] = stem + url = '/posts/{0}'.format(stem) + url = Remapper().remap_document(url) + post['url'] = url post['date'] = DateTimeSupport().rewrite_date(post['date']) data['posts'].append(post) diff --git a/src/data/environment/localhost.yml b/src/data/environment/localhost.yml index d29e905..b312ec7 100644 --- a/src/data/environment/localhost.yml +++ b/src/data/environment/localhost.yml @@ -25,7 +25,7 @@ server: thread_pool: 8 caching: - use: False + use: True tools: staticdirs: diff --git a/src/data/main_menu/settings.yml b/src/data/main_menu/settings.yml index c3afff2..e03f50f 100644 --- a/src/data/main_menu/settings.yml +++ b/src/data/main_menu/settings.yml @@ -4,4 +4,4 @@ ref: "/pages/about" - label: "Documentation" - ref: "/pages/docs" \ No newline at end of file + ref: "/pages/docs" diff --git a/src/data/posts/0013_version_1_5_1.md b/src/data/posts/0013_version_1_5_1.md index 25e0ceb..4f194d9 100644 --- a/src/data/posts/0013_version_1_5_1.md +++ b/src/data/posts/0013_version_1_5_1.md @@ -7,7 +7,7 @@ date: "2020-05-07" image: "cherry3.jpg" -summary: "Releasing a minor bug update" +summary: "Releasing a minor bug update." draft: False diff --git a/src/data/posts/0014_version_1_5_2.md b/src/data/posts/0014_version_1_5_2.md new file mode 100644 index 0000000..1218bed --- /dev/null +++ b/src/data/posts/0014_version_1_5_2.md @@ -0,0 +1,35 @@ +--- + +title: "Release v1.5.2" + +author: "Yves Vindevogel" +date: "2020-05-08" + +image: "cherry4.jpg" + +summary: "HOTFIX. Fixed Runtime-Error on posts and pages." + +draft: False + +tags: + - History + - Hotfix + +---------- + +HOTFIX. Fixed Runtime-Error on posts and pages. + +# Release info + +- author: Yves Vindevogel (vindevoy) +- date: 2020-05-08 + +# Hotfix + +- There was a runtime-error on the posts and pages if they had to tags. This resulted in a TypeError, and in code the KeyError was captured. + +### Github + +For more information on this release, see the issues for this milestone: + +- [https://github.com/vindevoy/cherryblog/milestone/15](https://github.com/vindevoy/cherryblog/milestone/15) \ No newline at end of file diff --git a/src/theme/default/elements/_html/highlight_post.html b/src/theme/default/elements/_html/highlight_post.html index eaedd7b..5f58660 100644 --- a/src/theme/default/elements/_html/highlight_post.html +++ b/src/theme/default/elements/_html/highlight_post.html @@ -1,14 +1,17 @@
    @@ -18,11 +21,17 @@ {% with author = post.author, date = post.date %} {% include 'elements/_html/card_footer.html' %} {% endwith %}
    -
\ No newline at end of file +
+ + diff --git a/src/theme/default/elements/_html/spotlight_post.html b/src/theme/default/elements/_html/spotlight_post.html index 9a20bb3..f34d47f 100644 --- a/src/theme/default/elements/_html/spotlight_post.html +++ b/src/theme/default/elements/_html/spotlight_post.html @@ -1,14 +1,17 @@
@@ -18,11 +21,17 @@ {% with author = post.author, date = post.date %} {% include 'elements/_html/card_footer.html' %} {% endwith %}
-
\ No newline at end of file +
+ + diff --git a/src/theme/default/elements/_html/standard_post.html b/src/theme/default/elements/_html/standard_post.html index be86068..eb73241 100644 --- a/src/theme/default/elements/_html/standard_post.html +++ b/src/theme/default/elements/_html/standard_post.html @@ -1,14 +1,17 @@
@@ -16,11 +19,17 @@ {% with author = post.author, date = post.date %} {% include 'elements/_html/card_footer.html' %} {% endwith %}
-
\ No newline at end of file + + + From 42c4db23e6595d9ef5fa0bddc57f5c3aafcc5efd Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Fri, 8 May 2020 17:30:43 +0200 Subject: [PATCH 20/21] Issue-114: Also updated sitemap --- src/application/sitemap.py | 31 +++++++++++++++++++++++++----- src/data/environment/localhost.yml | 2 +- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/application/sitemap.py b/src/application/sitemap.py index 2c39f78..b22cb8c 100644 --- a/src/application/sitemap.py +++ b/src/application/sitemap.py @@ -2,12 +2,12 @@ # # Full history: see below # -# Version: 1.0.0 -# Date: 2020-05-07 +# Version: 1.1.0 +# Date: 2020-05-08 # Author: Yves Vindevogel (vindevoy) # # Features: -# - Build a sitemap +# - Added remapper # ### @@ -20,6 +20,7 @@ from common.content import Content from controller.data_loader import DataLoader from controller.logging_loader import LoggingLoader +from controller.remapper import Remapper from controller.settings_loader import SettingsLoader environment = 'localhost' @@ -34,6 +35,9 @@ logger = logging.getLogger('SITEMAP') +Remapper().outgoing_content = DataLoader().mapping_outgoing() +Remapper().incoming_content = DataLoader().mapping_incoming() + # Override the drafts because Google will never find them in production most likely Options().include_drafts = False @@ -51,12 +55,15 @@ file = entry['file'] stem = Path(file).stem + unmapped = '/posts/{0}'.format(stem) + remapped = Remapper().remap_document(unmapped) + logger.info('Parsing {0}'.format(file)) meta, _, _ = Content().read_content('posts', file) xml += ' \n' - xml += ' https://cherryblog.org/posts/{0}\n'.format(stem) + xml += ' https://cherryblog.org{0}\n'.format(remapped) xml += ' {0}\n'.format(meta['date']) xml += ' never\n' xml += ' {0}\n'.format(round(priority, 2)) @@ -69,6 +76,9 @@ file = entry['file'] stem = Path(file).stem + unmapped = '/pages/{0}'.format(stem) + remapped = Remapper().remap_document(unmapped) + logger.info('Parsing {0}'.format(file)) meta, _, _ = Content().read_content('pages', file) @@ -84,7 +94,7 @@ update = 'monthly' xml += ' \n' - xml += ' https://cherryblog.org/pages/{0}\n'.format(stem) + xml += ' https://cherryblog.org{0}\n'.format(remapped) xml += ' {0}\n'.format(meta['date']) xml += ' {0}\n'.format(update) xml += ' {0}\n'.format(round(priority, 2)) @@ -96,3 +106,14 @@ sitemap_file = open(os.path.join(data_dir, 'sitemap', 'sitemap.xml'), 'w') sitemap_file.write(xml) sitemap_file.close() + +### +# +# Version: 1.0.0 +# Date: 2020-05-07 +# Author: Yves Vindevogel (vindevoy) +# +# Features: +# - Build a sitemap +# +### diff --git a/src/data/environment/localhost.yml b/src/data/environment/localhost.yml index b312ec7..d29e905 100644 --- a/src/data/environment/localhost.yml +++ b/src/data/environment/localhost.yml @@ -25,7 +25,7 @@ server: thread_pool: 8 caching: - use: True + use: False tools: staticdirs: From 1663f5f2f7ebccabd0a368754f323c26b0b5bda4 Mon Sep 17 00:00:00 2001 From: Yves Vindevogel Date: Sun, 17 May 2020 21:12:46 +0200 Subject: [PATCH 21/21] Preparing release 1.6.0 --- HISTORY.md | 61 +++++++++++++++++++++++++++ README.md | 3 ++ src/application/sitemap.py | 13 +++++- src/data/codeversion/settings.yml | 4 +- src/data/index/introduction.md | 3 ++ src/data/mapping/settings.yml | 26 ++++++++++++ src/data/pages/about.md | 3 ++ src/data/pages/releases.md | 63 +++++++++++++++++++++++++++- src/data/posts/0014_version_1_5_2.md | 4 +- src/data/posts/0015_version_1_6_0.md | 48 +++++++++++++++++++++ 10 files changed, 221 insertions(+), 7 deletions(-) create mode 100644 src/data/posts/0015_version_1_6_0.md diff --git a/HISTORY.md b/HISTORY.md index 052e150..96f0d18 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,64 @@ +# Release v1.6.0 + + +- author: Yves Vindevogel (vindevoy) +- date: 2020-05-17 + +## New Features + +- URL rerouting has been implemented on the level of the posts, pages and tags. This means that you can change the URL of the publication and through the rerouting, it will map the correct document(s). This can be used to make URLs more readable. +- Support for draft pages has been included. If you are writing a new post or page, but you don't want it to be published yet, you can put it as draft in the meta data. You can decide through the environment.yml if you want to show drafts or not (development vs. production). + +## Enhancements + +- A sitemap.xml file can be generated from the Makefile. This allows Google to crawl the website better. +- The application controller class now uses htmlmin to remove all the comment in the HTML, remove double spaces and so on. This results in a smaller HTML going over the wire, but it also results in a better memory footprint for caching. + +## Other + +- A Facebook page has been created for marketing reasons. Why else ? + +### Github + +For more information on this release, see the issues for this milestone: + +- [https://github.com/vindevoy/cherryblog/milestone/15](https://github.com/vindevoy/cherryblog/milestone/15) + + +# Release v1.5.2 + + +- author: Yves Vindevogel (vindevoy) +- date: 2020-05-08 + +## Hotfix + +- There was a runtime-error on the posts and pages if they had to tags. This resulted in a TypeError, and in code the KeyError was captured. + +### Github + +For more information on this release, see the issues for this milestone: + +- [https://github.com/vindevoy/cherryblog/milestone/15](https://github.com/vindevoy/cherryblog/milestone/15) + + +# Release v1.5.1 + + +- author: Yves Vindevogel (vindevoy) +- date: 2020-05-07 + +## Bug Fixes + +- There was a problem with the search results. The font weight (bold) of found text in the search results is now case-insensitive. + +### Github + +For more information on this release, see the issues for this milestone: + +- [https://github.com/vindevoy/cherryblog/milestone/14](https://github.com/vindevoy/cherryblog/milestone/14) + + # Release v1.5.0 diff --git a/README.md b/README.md index c45dbe4..9b3279f 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ CherryBlog implements a very simple blogging website. - Pages: the extra static pages like the 'about' - Tags: each post has one or multiple tags - Search: word based search in posts and pages +- Caching: in memory caching of data and content +- Drafts: drafts are pages that are not published yet, only visible in development +- URL rewriting: the final URL is not necessarily the path to the file At this moment, it has the basic news of the project where each article is a post about the new version that was released. diff --git a/src/application/sitemap.py b/src/application/sitemap.py index b22cb8c..385d7c3 100644 --- a/src/application/sitemap.py +++ b/src/application/sitemap.py @@ -35,6 +35,8 @@ logger = logging.getLogger('SITEMAP') +logger.debug('data_dir: {0}'.format(data_dir)) + Remapper().outgoing_content = DataLoader().mapping_outgoing() Remapper().incoming_content = DataLoader().mapping_incoming() @@ -58,12 +60,15 @@ unmapped = '/posts/{0}'.format(stem) remapped = Remapper().remap_document(unmapped) + logger.debug('unmapped: {0}'.format(unmapped)) + logger.debug('remapped: {0}'.format(remapped)) + logger.info('Parsing {0}'.format(file)) meta, _, _ = Content().read_content('posts', file) xml += ' \n' - xml += ' https://cherryblog.org{0}\n'.format(remapped) + xml += ' https://cherryblogger.org{0}\n'.format(remapped) xml += ' {0}\n'.format(meta['date']) xml += ' never\n' xml += ' {0}\n'.format(round(priority, 2)) @@ -102,8 +107,12 @@ xml += '\n' +logger.debug('xml:\n{0}'.format(xml)) + +sitemap_path = os.path.join(data_dir, 'sitemap', 'sitemap.xml') +logger.info('Writing file {0}'.format(sitemap_path)) -sitemap_file = open(os.path.join(data_dir, 'sitemap', 'sitemap.xml'), 'w') +sitemap_file = open(sitemap_path, 'w') sitemap_file.write(xml) sitemap_file.close() diff --git a/src/data/codeversion/settings.yml b/src/data/codeversion/settings.yml index 31940a4..9237a6f 100644 --- a/src/data/codeversion/settings.yml +++ b/src/data/codeversion/settings.yml @@ -1,5 +1,5 @@ --- text: - - 'Production: v.1.5.1 (master branch)' - - 'Next version: v.1.6.0 (develop branch)' \ No newline at end of file + - 'Production: v.1.6.0 (master branch)' + - 'Next version: v.1.7.0 (develop branch)' \ No newline at end of file diff --git a/src/data/index/introduction.md b/src/data/index/introduction.md index eec36c4..0a9fec8 100644 --- a/src/data/index/introduction.md +++ b/src/data/index/introduction.md @@ -10,6 +10,9 @@ CherryBlog implements a very simple blogging website. - Pages: the extra static pages like the 'about' - Tags: each post has one or multiple tags - Search: a word(s) based search on the posts and pages +- Caching: in memory caching of data and content +- Drafts: drafts are pages that are not published yet, only visible in development +- URL rewriting: the final URL is not necessarily the path to the file CherryBlog is written in Python 3 and uses Jinja2 templating. The default theme uses Bootstrap. CherryBlog uses CherryPy as web framework, hence its name. diff --git a/src/data/mapping/settings.yml b/src/data/mapping/settings.yml index 8af32ef..cf99254 100644 --- a/src/data/mapping/settings.yml +++ b/src/data/mapping/settings.yml @@ -5,3 +5,29 @@ content: source: 'posts/0001_announcement' - target: 'posts/version_1.0.0' source: 'posts/0002_version_1_0_0' + - target: 'posts/version_1.0.1' + source: 'posts/0003_version_1_0_1' + - target: 'posts/version_1.0.2' + source: 'posts/0004_version_1_0_2' + - target: 'posts/version_1.1.0' + source: 'posts/0005_version_1_1_0' + - target: 'posts/version_1.1.1' + source: 'posts/0006_version_1_1_1' + - target: 'posts/version_1.2.0' + source: 'posts/0007_version_1_2_0' + - target: 'posts/version_1.3.0' + source: 'posts/0008_version_1_3_0' + - target: 'posts/version_1.4.0' + source: 'posts/0009_version_1_4_0' + - target: 'posts/version_1.4.1' + source: 'posts/0010_version_1_4_1' + - target: 'posts/version_1.4.2' + source: 'posts/0011_version_1_4_2' + - target: 'posts/version_1.5.0' + source: 'posts/0012_version_1_5_0' + - target: 'posts/version_1.5.1' + source: 'posts/0013_version_1_5_1' + - target: 'posts/version_1.5.2' + source: 'posts/0014_version_1_5_2' + - target: 'posts/version_1.6.0' + source: 'posts/0015_version_1_6_0' diff --git a/src/data/pages/about.md b/src/data/pages/about.md index d0fe967..a506853 100644 --- a/src/data/pages/about.md +++ b/src/data/pages/about.md @@ -18,6 +18,9 @@ CherryBlog implements a very simple blogging website. - Pages: the extra static pages like the 'about' - Tags: each post has one or multiple tags - Search: word based search in posts and pages +- Caching: in memory caching of data and content +- Drafts: drafts are pages that are not published yet, only visible in development +- URL rewriting: the final URL is not necessarily the path to the file At this moment, it has the basic news of the project where each article is a post about the new version that was released. diff --git a/src/data/pages/releases.md b/src/data/pages/releases.md index 0e50a00..438bff9 100644 --- a/src/data/pages/releases.md +++ b/src/data/pages/releases.md @@ -5,10 +5,71 @@ title: "Release notes" image: "blossom4.jpg" author: "Yves Vindevogel" -date: "2020-05-01" +date: "2020-05-17" ---------- +# Release v1.6.0 + + +- author: Yves Vindevogel (vindevoy) +- date: 2020-05-17 + +## New Features + +- URL rerouting has been implemented on the level of the posts, pages and tags. This means that you can change the URL of the publication and through the rerouting, it will map the correct document(s). This can be used to make URLs more readable. +- Support for draft pages has been included. If you are writing a new post or page, but you don't want it to be published yet, you can put it as draft in the meta data. You can decide through the environment.yml if you want to show drafts or not (development vs. production). + +## Enhancements + +- A sitemap.xml file can be generated from the Makefile. This allows Google to crawl the website better. +- The application controller class now uses htmlmin to remove all the comment in the HTML, remove double spaces and so on. This results in a smaller HTML going over the wire, but it also results in a better memory footprint for caching. + +## Other + +- A Facebook page has been created for marketing reasons. Why else ? + +### Github + +For more information on this release, see the issues for this milestone: + +- [https://github.com/vindevoy/cherryblog/milestone/15](https://github.com/vindevoy/cherryblog/milestone/15) + + +# Release v1.5.2 + + +- author: Yves Vindevogel (vindevoy) +- date: 2020-05-08 + +## Hotfix + +- There was a runtime-error on the posts and pages if they had to tags. This resulted in a TypeError, and in code the KeyError was captured. + +### Github + +For more information on this release, see the issues for this milestone: + +- [https://github.com/vindevoy/cherryblog/milestone/15](https://github.com/vindevoy/cherryblog/milestone/15) + + +# Release v1.5.1 + + +- author: Yves Vindevogel (vindevoy) +- date: 2020-05-07 + +## Bug Fixes + +- There was a problem with the search results. The font weight (bold) of found text in the search results is now case-insensitive. + +### Github + +For more information on this release, see the issues for this milestone: + +- [https://github.com/vindevoy/cherryblog/milestone/14](https://github.com/vindevoy/cherryblog/milestone/14) + + # Release v1.5.0 diff --git a/src/data/posts/0014_version_1_5_2.md b/src/data/posts/0014_version_1_5_2.md index 1218bed..097dfcd 100644 --- a/src/data/posts/0014_version_1_5_2.md +++ b/src/data/posts/0014_version_1_5_2.md @@ -19,12 +19,12 @@ tags: HOTFIX. Fixed Runtime-Error on posts and pages. -# Release info +## Release info - author: Yves Vindevogel (vindevoy) - date: 2020-05-08 -# Hotfix +## Hotfix - There was a runtime-error on the posts and pages if they had to tags. This resulted in a TypeError, and in code the KeyError was captured. diff --git a/src/data/posts/0015_version_1_6_0.md b/src/data/posts/0015_version_1_6_0.md new file mode 100644 index 0000000..9c1746d --- /dev/null +++ b/src/data/posts/0015_version_1_6_0.md @@ -0,0 +1,48 @@ +--- + +title: "Release v1.6.0" + +author: "Yves Vindevogel" +date: "2020-05-17" + +image: "cherry2.jpg" + +summary: "A new set of features, like URL rerouting and support for draft pages has been implemented in this version. In the background, CherryBlog is now sending minified HTML and Google can use the sitemap to crawl the website." + +draft: False + +tags: + - History + - Enhancements + - New Features + +---------- + +A new set of features, like URL rerouting and support for draft pages has been implemented in this version. In the background, CherryBlog is now sending minified HTML and Google can use the sitemap to crawl the website. + +This release is a bit later than foreseen, due to time limits. These features were ready last week, but I wanted to include another feature, which is not yet finished. Therefore, I decided to release this already as there are quite some interesting changes. + +## Release info + +- author: Yves Vindevogel (vindevoy) +- date: 2020-05-17 + +## New Features + +- URL rerouting has been implemented on the level of the posts, pages and tags. This means that you can change the URL of the publication and through the rerouting, it will map the correct document(s). This can be used to make URLs more readable. +- Support for draft pages has been included. If you are writing a new post or page, but you don't want it to be published yet, you can put it as draft in the meta data. You can decide through the environment.yml if you want to show drafts or not (development vs. production). + +## Enhancements + +- A sitemap.xml file can be generated from the Makefile. This allows Google to crawl the website better. +- The application controller class now uses htmlmin to remove all the comment in the HTML, remove double spaces and so on. This results in a smaller HTML going over the wire, but it also results in a better memory footprint for caching. + +## Other + +- A Facebook page has been created for marketing reasons. Why else ? + +### Github + +For more information on this release, see the issues for this milestone: + +- [https://github.com/vindevoy/cherryblog/milestone/15](https://github.com/vindevoy/cherryblog/milestone/15) \ No newline at end of file