mirror of
https://github.com/getpelican/pelican.git
synced 2025-10-15 20:28:56 +02:00
Add support for hidden articles
This commit is contained in:
parent
487da3550b
commit
add3628a64
8 changed files with 70 additions and 14 deletions
|
|
@ -614,6 +614,14 @@ the ``DEFAULT_METADATA``::
|
||||||
To publish a post when the default status is ``draft``, update the post's
|
To publish a post when the default status is ``draft``, update the post's
|
||||||
metadata to include ``Status: published``.
|
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
|
.. _W3C ISO 8601: https://www.w3.org/TR/NOTE-datetime
|
||||||
.. _AsciiDoc: https://www.methods.co.nz/asciidoc/
|
.. _AsciiDoc: https://www.methods.co.nz/asciidoc/
|
||||||
.. _pelican-plugins: https://github.com/getpelican/pelican-plugins
|
.. _pelican-plugins: https://github.com/getpelican/pelican-plugins
|
||||||
|
|
|
||||||
|
|
@ -66,9 +66,9 @@ Common variables
|
||||||
|
|
||||||
All of these settings will be available to all templates.
|
All of these settings will be available to all templates.
|
||||||
|
|
||||||
============= ===================================================
|
=============== ===================================================
|
||||||
Variable Description
|
Variable Description
|
||||||
============= ===================================================
|
=============== ===================================================
|
||||||
output_file The name of the file currently being generated. For
|
output_file The name of the file currently being generated. For
|
||||||
instance, when Pelican is rendering the home page,
|
instance, when Pelican is rendering the home page,
|
||||||
output_file will be "index.html".
|
output_file will be "index.html".
|
||||||
|
|
@ -80,6 +80,7 @@ articles The list of articles, ordered descending by date.
|
||||||
in the `all_articles` variable.
|
in the `all_articles` variable.
|
||||||
dates The same list of articles, but ordered by date,
|
dates The same list of articles, but ordered by date,
|
||||||
ascending.
|
ascending.
|
||||||
|
hidden_articles The list of hidden articles
|
||||||
drafts The list of draft articles
|
drafts The list of draft articles
|
||||||
authors A list of (author, articles) tuples, containing all
|
authors A list of (author, articles) tuples, containing all
|
||||||
the authors and corresponding articles (values)
|
the authors and corresponding articles (values)
|
||||||
|
|
@ -90,7 +91,7 @@ tags A list of (tag, articles) tuples, containing all
|
||||||
pages The list of pages
|
pages The list of pages
|
||||||
hidden_pages The list of hidden pages
|
hidden_pages The list of hidden pages
|
||||||
draft_pages The list of draft pages
|
draft_pages The list of draft pages
|
||||||
============= ===================================================
|
=============== ===================================================
|
||||||
|
|
||||||
|
|
||||||
Sorting
|
Sorting
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,11 @@ class Pelican:
|
||||||
len(articles_generator.drafts_translations)),
|
len(articles_generator.drafts_translations)),
|
||||||
'draft',
|
'draft',
|
||||||
'drafts')
|
'drafts')
|
||||||
|
pluralized_hidden_articles = maybe_pluralize(
|
||||||
|
(len(articles_generator.hidden_articles) +
|
||||||
|
len(articles_generator.hidden_translations)),
|
||||||
|
'hidden article',
|
||||||
|
'hidden articles')
|
||||||
pluralized_pages = maybe_pluralize(
|
pluralized_pages = maybe_pluralize(
|
||||||
(len(pages_generator.pages) +
|
(len(pages_generator.pages) +
|
||||||
len(pages_generator.translations)),
|
len(pages_generator.translations)),
|
||||||
|
|
@ -160,10 +165,11 @@ class Pelican:
|
||||||
'draft page',
|
'draft page',
|
||||||
'draft pages')
|
'draft pages')
|
||||||
|
|
||||||
print('Done: Processed {}, {}, {}, {} and {} in {:.2f} seconds.'
|
print('Done: Processed {}, {}, {}, {}, {} and {} in {:.2f} seconds.'
|
||||||
.format(
|
.format(
|
||||||
pluralized_articles,
|
pluralized_articles,
|
||||||
pluralized_drafts,
|
pluralized_drafts,
|
||||||
|
pluralized_hidden_articles,
|
||||||
pluralized_pages,
|
pluralized_pages,
|
||||||
pluralized_hidden_pages,
|
pluralized_hidden_pages,
|
||||||
pluralized_draft_pages,
|
pluralized_draft_pages,
|
||||||
|
|
|
||||||
|
|
@ -181,9 +181,9 @@ class Content:
|
||||||
if hasattr(self, 'allowed_statuses'):
|
if hasattr(self, 'allowed_statuses'):
|
||||||
if self.status not in self.allowed_statuses:
|
if self.status not in self.allowed_statuses:
|
||||||
logger.error(
|
logger.error(
|
||||||
"Unknown status '%s' for file %s, skipping it.",
|
"Unknown status '%s' for file %s, skipping it. (Not in %s)",
|
||||||
self.status,
|
self.status,
|
||||||
self
|
self, self.allowed_statuses
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -513,7 +513,7 @@ class Page(Content):
|
||||||
|
|
||||||
class Article(Content):
|
class Article(Content):
|
||||||
mandatory_properties = ('title', 'date', 'category')
|
mandatory_properties = ('title', 'date', 'category')
|
||||||
allowed_statuses = ('published', 'draft')
|
allowed_statuses = ('published', 'hidden', 'draft')
|
||||||
default_status = 'published'
|
default_status = 'published'
|
||||||
default_template = 'article'
|
default_template = 'article'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -285,15 +285,20 @@ class ArticlesGenerator(CachingGenerator):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
"""initialize properties"""
|
"""initialize properties"""
|
||||||
|
# Published, listed articles
|
||||||
self.articles = [] # only articles in default language
|
self.articles = [] # only articles in default language
|
||||||
self.translations = []
|
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.dates = {}
|
||||||
self.tags = defaultdict(list)
|
self.tags = defaultdict(list)
|
||||||
self.categories = defaultdict(list)
|
self.categories = defaultdict(list)
|
||||||
self.related_posts = []
|
self.related_posts = []
|
||||||
self.authors = defaultdict(list)
|
self.authors = defaultdict(list)
|
||||||
self.drafts = [] # only drafts in default language
|
|
||||||
self.drafts_translations = []
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
signals.article_generator_init.send(self)
|
signals.article_generator_init.send(self)
|
||||||
|
|
||||||
|
|
@ -461,7 +466,10 @@ class ArticlesGenerator(CachingGenerator):
|
||||||
|
|
||||||
def generate_articles(self, write):
|
def generate_articles(self, write):
|
||||||
"""Generate the articles."""
|
"""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)
|
signals.article_generator_write_article.send(self, content=article)
|
||||||
write(article.save_as, self.get_template(article.template),
|
write(article.save_as, self.get_template(article.template),
|
||||||
self.context, article=article, category=article.category,
|
self.context, article=article, category=article.category,
|
||||||
|
|
@ -609,6 +617,7 @@ class ArticlesGenerator(CachingGenerator):
|
||||||
|
|
||||||
all_articles = []
|
all_articles = []
|
||||||
all_drafts = []
|
all_drafts = []
|
||||||
|
hidden_articles = []
|
||||||
for f in self.get_files(
|
for f in self.get_files(
|
||||||
self.settings['ARTICLE_PATHS'],
|
self.settings['ARTICLE_PATHS'],
|
||||||
exclude=self.settings['ARTICLE_EXCLUDES']):
|
exclude=self.settings['ARTICLE_EXCLUDES']):
|
||||||
|
|
@ -639,6 +648,9 @@ class ArticlesGenerator(CachingGenerator):
|
||||||
all_articles.append(article)
|
all_articles.append(article)
|
||||||
elif article.status == "draft":
|
elif article.status == "draft":
|
||||||
all_drafts.append(article)
|
all_drafts.append(article)
|
||||||
|
elif article.status == "hidden":
|
||||||
|
hidden_articles.append(article)
|
||||||
|
|
||||||
self.add_source_path(article)
|
self.add_source_path(article)
|
||||||
self.add_static_links(article)
|
self.add_static_links(article)
|
||||||
|
|
||||||
|
|
@ -649,13 +661,14 @@ class ArticlesGenerator(CachingGenerator):
|
||||||
return origs, translations
|
return origs, translations
|
||||||
|
|
||||||
self.articles, self.translations = _process(all_articles)
|
self.articles, self.translations = _process(all_articles)
|
||||||
|
self.hidden_articles, self.hidden_translations = _process(hidden_articles)
|
||||||
self.drafts, self.drafts_translations = _process(all_drafts)
|
self.drafts, self.drafts_translations = _process(all_drafts)
|
||||||
|
|
||||||
signals.article_generator_pretaxonomy.send(self)
|
signals.article_generator_pretaxonomy.send(self)
|
||||||
|
|
||||||
for article in self.articles:
|
for article in self.articles:
|
||||||
# only main articles are listed in categories and tags
|
# only main articles are listed in categories and tags
|
||||||
# not translations
|
# not translations or hidden articles
|
||||||
self.categories[article.category].append(article)
|
self.categories[article.category].append(article)
|
||||||
if hasattr(article, 'tags'):
|
if hasattr(article, 'tags'):
|
||||||
for tag in article.tags:
|
for tag in article.tags:
|
||||||
|
|
@ -677,8 +690,10 @@ class ArticlesGenerator(CachingGenerator):
|
||||||
self.authors = list(self.authors.items())
|
self.authors = list(self.authors.items())
|
||||||
self.authors.sort()
|
self.authors.sort()
|
||||||
|
|
||||||
self._update_context(('articles', 'dates', 'tags', 'categories',
|
self._update_context((
|
||||||
'authors', 'related_posts', 'drafts'))
|
'articles', 'drafts', 'hidden_articles',
|
||||||
|
'dates', 'tags', 'categories',
|
||||||
|
'authors', 'related_posts'))
|
||||||
self.save_cache()
|
self.save_cache()
|
||||||
self.readers.save_cache()
|
self.readers.save_cache()
|
||||||
signals.article_generator_finalized.send(self)
|
signals.article_generator_finalized.send(self)
|
||||||
|
|
@ -692,7 +707,9 @@ class ArticlesGenerator(CachingGenerator):
|
||||||
for e in chain(self.articles,
|
for e in chain(self.articles,
|
||||||
self.translations,
|
self.translations,
|
||||||
self.drafts,
|
self.drafts,
|
||||||
self.drafts_translations):
|
self.drafts_translations,
|
||||||
|
self.hidden_articles,
|
||||||
|
self.hidden_translations):
|
||||||
if hasattr(e, 'refresh_metadata_intersite_links'):
|
if hasattr(e, 'refresh_metadata_intersite_links'):
|
||||||
e.refresh_metadata_intersite_links()
|
e.refresh_metadata_intersite_links()
|
||||||
|
|
||||||
|
|
|
||||||
5
pelican/tests/content/article_draft.md
vendored
Normal file
5
pelican/tests/content/article_draft.md
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
Title: Draft article
|
||||||
|
Date: 2012-10-31
|
||||||
|
Status: draft
|
||||||
|
|
||||||
|
This is some content.
|
||||||
5
pelican/tests/content/article_hidden.md
vendored
Normal file
5
pelican/tests/content/article_hidden.md
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
Title: Hidden article
|
||||||
|
Date: 2012-10-31
|
||||||
|
Status: hidden
|
||||||
|
|
||||||
|
This is some unlisted content.
|
||||||
|
|
@ -181,6 +181,8 @@ class TestArticlesGenerator(unittest.TestCase):
|
||||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||||
cls.generator.generate_context()
|
cls.generator.generate_context()
|
||||||
cls.articles = cls.distill_articles(cls.generator.articles)
|
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):
|
def setUp(self):
|
||||||
self.temp_cache = mkdtemp(prefix='pelican_cache.')
|
self.temp_cache = mkdtemp(prefix='pelican_cache.')
|
||||||
|
|
@ -284,6 +286,18 @@ class TestArticlesGenerator(unittest.TestCase):
|
||||||
]
|
]
|
||||||
self.assertEqual(sorted(articles_expected), sorted(self.articles))
|
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):
|
def test_generate_categories(self):
|
||||||
# test for name
|
# test for name
|
||||||
# categories are grouped by slug; if two categories have the same slug
|
# categories are grouped by slug; if two categories have the same slug
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue