From add3628a6474f2bd145fe2ea55c5e5255e9970ba Mon Sep 17 00:00:00 2001 From: Gio Date: Fri, 16 Apr 2021 19:07:35 -0500 Subject: [PATCH] Add support for hidden articles --- docs/content.rst | 8 +++++++ docs/themes.rst | 7 +++--- pelican/__init__.py | 8 ++++++- pelican/contents.py | 6 ++--- pelican/generators.py | 31 +++++++++++++++++++------ pelican/tests/content/article_draft.md | 5 ++++ pelican/tests/content/article_hidden.md | 5 ++++ pelican/tests/test_generators.py | 14 +++++++++++ 8 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 pelican/tests/content/article_draft.md create mode 100644 pelican/tests/content/article_hidden.md diff --git a/docs/content.rst b/docs/content.rst index 48c851ab..cd492012 100644 --- a/docs/content.rst +++ b/docs/content.rst @@ -614,6 +614,14 @@ the ``DEFAULT_METADATA``:: To publish a post when the default status is ``draft``, update the post's metadata to include ``Status: published``. +Hidden Posts +============ + +Like pages, posts can also be marked as ``hidden`` with the ``Status: hidden`` +attribute. Hidden posts will be output to ``ARTICLE_SAVE_AS`` as expected, but +are not included by default in tag or category indexes, nor in the main +article feed. This has the effect of creating an "unlisted" post. + .. _W3C ISO 8601: https://www.w3.org/TR/NOTE-datetime .. _AsciiDoc: https://www.methods.co.nz/asciidoc/ .. _pelican-plugins: https://github.com/getpelican/pelican-plugins diff --git a/docs/themes.rst b/docs/themes.rst index 0c053fce..c4d3ed7f 100644 --- a/docs/themes.rst +++ b/docs/themes.rst @@ -66,9 +66,9 @@ Common variables All of these settings will be available to all templates. -============= =================================================== +=============== =================================================== Variable Description -============= =================================================== +=============== =================================================== output_file The name of the file currently being generated. For instance, when Pelican is rendering the home page, output_file will be "index.html". @@ -80,6 +80,7 @@ articles The list of articles, ordered descending by date. in the `all_articles` variable. dates The same list of articles, but ordered by date, ascending. +hidden_articles The list of hidden articles drafts The list of draft articles authors A list of (author, articles) tuples, containing all the authors and corresponding articles (values) @@ -90,7 +91,7 @@ tags A list of (tag, articles) tuples, containing all pages The list of pages hidden_pages The list of hidden pages draft_pages The list of draft pages -============= =================================================== +=============== =================================================== Sorting diff --git a/pelican/__init__.py b/pelican/__init__.py index 6302fe21..735002a2 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -144,6 +144,11 @@ class Pelican: len(articles_generator.drafts_translations)), 'draft', 'drafts') + pluralized_hidden_articles = maybe_pluralize( + (len(articles_generator.hidden_articles) + + len(articles_generator.hidden_translations)), + 'hidden article', + 'hidden articles') pluralized_pages = maybe_pluralize( (len(pages_generator.pages) + len(pages_generator.translations)), @@ -160,10 +165,11 @@ class Pelican: 'draft page', 'draft pages') - print('Done: Processed {}, {}, {}, {} and {} in {:.2f} seconds.' + print('Done: Processed {}, {}, {}, {}, {} and {} in {:.2f} seconds.' .format( pluralized_articles, pluralized_drafts, + pluralized_hidden_articles, pluralized_pages, pluralized_hidden_pages, pluralized_draft_pages, diff --git a/pelican/contents.py b/pelican/contents.py index 75cedcdc..1740df88 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -181,9 +181,9 @@ class Content: if hasattr(self, 'allowed_statuses'): if self.status not in self.allowed_statuses: logger.error( - "Unknown status '%s' for file %s, skipping it.", + "Unknown status '%s' for file %s, skipping it. (Not in %s)", self.status, - self + self, self.allowed_statuses ) return False @@ -513,7 +513,7 @@ class Page(Content): class Article(Content): mandatory_properties = ('title', 'date', 'category') - allowed_statuses = ('published', 'draft') + allowed_statuses = ('published', 'hidden', 'draft') default_status = 'published' default_template = 'article' diff --git a/pelican/generators.py b/pelican/generators.py index 07370264..85bc3d95 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -285,15 +285,20 @@ class ArticlesGenerator(CachingGenerator): def __init__(self, *args, **kwargs): """initialize properties""" + # Published, listed articles self.articles = [] # only articles in default language self.translations = [] + # Published, unlisted articles + self.hidden_articles = [] + self.hidden_translations = [] + # Draft articles + self.drafts = [] # only drafts in default language + self.drafts_translations = [] self.dates = {} self.tags = defaultdict(list) self.categories = defaultdict(list) self.related_posts = [] self.authors = defaultdict(list) - self.drafts = [] # only drafts in default language - self.drafts_translations = [] super().__init__(*args, **kwargs) signals.article_generator_init.send(self) @@ -461,7 +466,10 @@ class ArticlesGenerator(CachingGenerator): def generate_articles(self, write): """Generate the articles.""" - for article in chain(self.translations, self.articles): + for article in chain( + self.translations, self.articles, + self.hidden_translations, self.hidden_articles + ): signals.article_generator_write_article.send(self, content=article) write(article.save_as, self.get_template(article.template), self.context, article=article, category=article.category, @@ -609,6 +617,7 @@ class ArticlesGenerator(CachingGenerator): all_articles = [] all_drafts = [] + hidden_articles = [] for f in self.get_files( self.settings['ARTICLE_PATHS'], exclude=self.settings['ARTICLE_EXCLUDES']): @@ -639,6 +648,9 @@ class ArticlesGenerator(CachingGenerator): all_articles.append(article) elif article.status == "draft": all_drafts.append(article) + elif article.status == "hidden": + hidden_articles.append(article) + self.add_source_path(article) self.add_static_links(article) @@ -649,13 +661,14 @@ class ArticlesGenerator(CachingGenerator): return origs, translations self.articles, self.translations = _process(all_articles) + self.hidden_articles, self.hidden_translations = _process(hidden_articles) self.drafts, self.drafts_translations = _process(all_drafts) signals.article_generator_pretaxonomy.send(self) for article in self.articles: # only main articles are listed in categories and tags - # not translations + # not translations or hidden articles self.categories[article.category].append(article) if hasattr(article, 'tags'): for tag in article.tags: @@ -677,8 +690,10 @@ class ArticlesGenerator(CachingGenerator): self.authors = list(self.authors.items()) self.authors.sort() - self._update_context(('articles', 'dates', 'tags', 'categories', - 'authors', 'related_posts', 'drafts')) + self._update_context(( + 'articles', 'drafts', 'hidden_articles', + 'dates', 'tags', 'categories', + 'authors', 'related_posts')) self.save_cache() self.readers.save_cache() signals.article_generator_finalized.send(self) @@ -692,7 +707,9 @@ class ArticlesGenerator(CachingGenerator): for e in chain(self.articles, self.translations, self.drafts, - self.drafts_translations): + self.drafts_translations, + self.hidden_articles, + self.hidden_translations): if hasattr(e, 'refresh_metadata_intersite_links'): e.refresh_metadata_intersite_links() diff --git a/pelican/tests/content/article_draft.md b/pelican/tests/content/article_draft.md new file mode 100644 index 00000000..d2235553 --- /dev/null +++ b/pelican/tests/content/article_draft.md @@ -0,0 +1,5 @@ +Title: Draft article +Date: 2012-10-31 +Status: draft + +This is some content. diff --git a/pelican/tests/content/article_hidden.md b/pelican/tests/content/article_hidden.md new file mode 100644 index 00000000..d449f701 --- /dev/null +++ b/pelican/tests/content/article_hidden.md @@ -0,0 +1,5 @@ +Title: Hidden article +Date: 2012-10-31 +Status: hidden + +This is some unlisted content. diff --git a/pelican/tests/test_generators.py b/pelican/tests/test_generators.py index be43aa0e..0a4a8fdc 100644 --- a/pelican/tests/test_generators.py +++ b/pelican/tests/test_generators.py @@ -181,6 +181,8 @@ class TestArticlesGenerator(unittest.TestCase): path=CONTENT_DIR, theme=settings['THEME'], output_path=None) cls.generator.generate_context() cls.articles = cls.distill_articles(cls.generator.articles) + cls.drafts = cls.distill_articles(cls.generator.drafts) + cls.hidden_articles = cls.distill_articles(cls.generator.hidden_articles) def setUp(self): self.temp_cache = mkdtemp(prefix='pelican_cache.') @@ -284,6 +286,18 @@ class TestArticlesGenerator(unittest.TestCase): ] self.assertEqual(sorted(articles_expected), sorted(self.articles)) + def test_articles_draft(self): + draft_articles_expected = [ + ['Draft article', 'draft', 'Default', 'article'], + ] + self.assertEqual(sorted(draft_articles_expected), sorted(self.drafts)) + + def test_articles_hidden(self): + hidden_articles_expected = [ + ['Hidden article', 'hidden', 'Default', 'article'], + ] + self.assertEqual(sorted(hidden_articles_expected), sorted(self.hidden_articles)) + def test_generate_categories(self): # test for name # categories are grouped by slug; if two categories have the same slug