aboutsummaryrefslogtreecommitdiff
path: root/infra/website/plugins
diff options
context:
space:
mode:
authorMx Kookie <kookie@spacekookie.de>2020-10-31 19:50:28 +0100
committerMx Kookie <kookie@spacekookie.de>2020-12-21 05:10:49 +0100
commit6446d904a67e48a23c9e6e852f4931de9fc41013 (patch)
tree99448ad3d5f8a098dda781c0764a3932a6428c89 /infra/website/plugins
parent221c787583d88edac151999b0b78e3e1cab68cfb (diff)
Add 'infra/website/' from commit '275bec94f9f9e221bfddeb06ca7d5b87068eb7a0'
git-subtree-dir: infra/website git-subtree-mainline: c4625b175f8200f643fd6e11010932ea44c78433 git-subtree-split: 275bec94f9f9e221bfddeb06ca7d5b87068eb7a0
Diffstat (limited to 'infra/website/plugins')
-rw-r--r--infra/website/plugins/read_time/README.md72
-rw-r--r--infra/website/plugins/read_time/__init__.py1
-rw-r--r--infra/website/plugins/read_time/read_time.py113
-rwxr-xr-xinfra/website/plugins/summary/Readme.rst53
-rwxr-xr-xinfra/website/plugins/summary/__init__.py1
-rwxr-xr-xinfra/website/plugins/summary/summary.py90
-rwxr-xr-xinfra/website/plugins/summary/test_summary.py75
7 files changed, 405 insertions, 0 deletions
diff --git a/infra/website/plugins/read_time/README.md b/infra/website/plugins/read_time/README.md
new file mode 100644
index 000000000000..60c785d13998
--- /dev/null
+++ b/infra/website/plugins/read_time/README.md
@@ -0,0 +1,72 @@
+Read Time
+===================================
+
+This plugin calculates the read time for each article based on the number of words and an average words per minute count. There are two ways to set up the plugin: using words per minute only or using the more advanced language option.
+
+## Setting Up
+#### Adding to pelican conf
+
+Add the following entry to the `PLUGINS` array
+
+***pelicanconf.py***
+```
+PLUGINS = ['read_time']
+```
+
+#### 1. Words Per Minute Only
+
+In your settings you would use assign the `READ_TIME` variable to an integer like so:
+
+***pelicanconf.py***
+```
+READ_TIME = 180
+```
+
+Every article's read time would be calculated using this average words per minute count. (See the Usage section for how to use the calculated read times in templates). This is the simplest read time method.
+
+#### 2. Words Per Minute per language
+
+This is the preferred method if you are dealing with multiple languages. Take a look at the following settings
+
+
+***pelicanconf.py***
+```
+READ_TIME = {
+ 'default': {
+ 'wpm': 180,
+ 'plurals': ['minute', 'minutes']
+ },
+ 'es': {
+ 'wpm': 200,
+ 'plurals': ['minuto', 'minutos']
+ },
+ 'it': {
+ 'plurals': ['minuto', 'minuti']
+ }
+}
+```
+
+
+In this example the default reading time for all articles is 180 words per minute. Any articles in spanish will be calculated at 200 wpm. This is useful for information dense languages where the read time varies rapidly.
+
+Also notice the Italian language, the read time for all italian articles will be 180wpm (the default value). However, the article will also be able to take advantage of the plurality option. An italian article that takes four minutes to read will have access to a variable that prints "4 minuti". (See the Usage section for how to use the calculated read times in templates)
+
+Chances are the average reading time will not vary rapidly from language to language, however using this method also allows you to set plurals which make templating easier in the long run.
+
+## Usage
+
+Two variables are accessible through the read time plugin, **read_time** and **read_time_string**
+
+```
+This article takes {{article.read_time}} minute(s) to read.
+// This article takes 4 minute(s) to read
+```
+
+```
+This article takes {{article.read_time_string}} to read.
+// This article takes 4 minutes to read
+```
+
+## Contact
+
+Deepak Bhalla https://deepakrb.com 2016 \ No newline at end of file
diff --git a/infra/website/plugins/read_time/__init__.py b/infra/website/plugins/read_time/__init__.py
new file mode 100644
index 000000000000..fb84126d79c0
--- /dev/null
+++ b/infra/website/plugins/read_time/__init__.py
@@ -0,0 +1 @@
+from .read_time import * \ No newline at end of file
diff --git a/infra/website/plugins/read_time/read_time.py b/infra/website/plugins/read_time/read_time.py
new file mode 100644
index 000000000000..f7b978beb9a7
--- /dev/null
+++ b/infra/website/plugins/read_time/read_time.py
@@ -0,0 +1,113 @@
+from pelican import signals
+from itertools import chain
+import datetime
+
+def init(generator):
+ data = {
+ 'default': {
+ 'wpm': 200,
+ 'plurals': [
+ 'minute',
+ 'minutes'
+ ]
+ }
+ }
+
+ settings_wpm = generator.settings.get('READ_TIME', data)
+
+ # Allows a wpm entry
+ if isinstance(settings_wpm, int):
+ data['default']['wpm'] = settings_wpm
+
+ # Default checker
+ if isinstance(settings_wpm, dict):
+ if 'default' not in settings_wpm:
+ return None
+ if 'wpm' not in settings_wpm['default']:
+ return None
+ if 'plurals' not in settings_wpm['default']:
+ return None
+ if not isinstance(settings_wpm['default']['wpm'], int):
+ return None
+ if not isinstance(settings_wpm['default']['plurals'], list):
+ return None
+ if len(settings_wpm['default']['plurals']) != 2:
+ return None
+ data = settings_wpm
+
+ for article in chain(generator.articles, generator.drafts, generator.translations, generator.drafts_translations):
+ language = 'default'
+ if article.lang in data:
+ language = article.lang
+ # Exit if read time is set by article
+ if hasattr(article, 'read_time'):
+ return None
+
+ article.read_time = calculate_wpm(article.content, data, language)
+ article.read_time_string = generate_string(
+ article.read_time, data, language)
+
+def calculate_wpm(text, data, language):
+ '''
+ Calculates read length of article
+ '''
+
+ try:
+ wpm = data[language]['wpm']
+ except LookupError:
+ wpm = data['default']['wpm']
+
+ # Split out "appendix" sections at the end
+ new_text = ""
+ skipping = False
+ for word in text.split(' '):
+ print(word)
+ if '<skip>' in word:
+ skipping = True
+ elif '<pre>' in word:
+ skipping = True
+
+ if not skipping:
+ new_text += word + ' '
+
+ if '</skip>' in word:
+ skipping = False
+ elif '</pre>' in word:
+ skipping = False
+
+ read_time = len(new_text.split(' ')) / wpm
+
+ # Articles cannot take 0 minutes to read
+ if read_time == 0:
+ return 1
+
+ return read_time
+
+
+def generate_string(read_time, data, language):
+ '''
+ Generates read length as string with appropriate plurality i.e 1 minute, 4 minutes
+ '''
+
+ try:
+ non_plural = data[language]['plurals'][0]
+ except LookupError:
+ non_plural = data['default']['plurals'][0]
+
+ try:
+ plural = data[language]['plurals'][1]
+ except LookupError:
+ plural = data['default']['plurals'][1]
+
+ td = datetime.timedelta(minutes=read_time)
+ seconds = td.total_seconds()
+ read_time = '%02d:%02d' % (seconds / 60 % 60, seconds % 60)
+
+ if read_time != 1:
+ return '{0} {1}'.format(read_time, plural)
+
+ return '{0} {1}'.format(read_time, non_plural)
+
+
+def register():
+ signals.article_generator_finalized.connect(init)
diff --git a/infra/website/plugins/summary/Readme.rst b/infra/website/plugins/summary/Readme.rst
new file mode 100755
index 000000000000..3aec268a0665
--- /dev/null
+++ b/infra/website/plugins/summary/Readme.rst
@@ -0,0 +1,53 @@
+Summary
+-------
+
+This plugin allows easy, variable length summaries directly embedded into the
+body of your articles. It introduces two new settings: ``SUMMARY_BEGIN_MARKER``
+and ``SUMMARY_END_MARKER``: strings which can be placed directly into an article
+to mark the beginning and end of a summary. When found, the standard
+``SUMMARY_MAX_LENGTH`` setting will be ignored. The markers themselves will also
+be removed from your articles before they are published. The default values
+are ``<!-- PELICAN_BEGIN_SUMMARY -->`` and ``<!-- PELICAN_END_SUMMARY -->``.
+For example::
+
+ Title: My super title
+ Date: 2010-12-03 10:20
+ Tags: thats, awesome
+ Category: yeah
+ Slug: my-super-post
+ Author: Alexis Metaireau
+
+ This is the content of my super blog post.
+ <!-- PELICAN_END_SUMMARY -->
+ and this content occurs after the summary.
+
+Here, the summary is taken to be the first line of the post. Because no
+beginning marker was found, it starts at the top of the body. It is possible
+to leave out the end marker instead, in which case the summary will start at the
+beginning marker and continue to the end of the body.
+
+The plugin also sets a ``has_summary`` attribute on every article. It is True
+for articles with an explicitly-defined summary, and False otherwise. (It is
+also False for an article truncated by ``SUMMARY_MAX_LENGTH``.) Your templates
+can use this e.g. to add a link to the full text at the end of the summary.
+
+reST example
+~~~~~~~~~~~~
+
+Inserting the markers into a reStructuredText document makes use of the
+comment directive, because raw HTML is automatically escaped. The reST equivalent of the above Markdown example looks like this::
+
+ My super title
+ ##############
+
+ :date: 2010-12-03 10:20
+ :tags: thats, awesome
+ :category: yeah
+ :slug: my-super-post
+ :author: Alexis Metaireau
+
+ This is the content of my super blog post.
+
+ .. PELICAN_END_SUMMARY
+
+ and this content occurs after the summary.
diff --git a/infra/website/plugins/summary/__init__.py b/infra/website/plugins/summary/__init__.py
new file mode 100755
index 000000000000..afe9311f2db2
--- /dev/null
+++ b/infra/website/plugins/summary/__init__.py
@@ -0,0 +1 @@
+from .summary import *
diff --git a/infra/website/plugins/summary/summary.py b/infra/website/plugins/summary/summary.py
new file mode 100755
index 000000000000..365f08f3fb9b
--- /dev/null
+++ b/infra/website/plugins/summary/summary.py
@@ -0,0 +1,90 @@
+"""
+Summary
+-------
+
+This plugin allows easy, variable length summaries directly embedded into the
+body of your articles.
+"""
+
+from __future__ import unicode_literals
+from pelican import signals
+from pelican.generators import ArticlesGenerator, StaticGenerator, PagesGenerator
+
+def initialized(pelican):
+ from pelican.settings import DEFAULT_CONFIG
+ DEFAULT_CONFIG.setdefault('SUMMARY_BEGIN_MARKER',
+ '<!-- PELICAN_BEGIN_SUMMARY -->')
+ DEFAULT_CONFIG.setdefault('SUMMARY_END_MARKER',
+ '<!-- PELICAN_END_SUMMARY -->')
+ if pelican:
+ pelican.settings.setdefault('SUMMARY_BEGIN_MARKER',
+ '<!-- PELICAN_BEGIN_SUMMARY -->')
+ pelican.settings.setdefault('SUMMARY_END_MARKER',
+ '<!-- PELICAN_END_SUMMARY -->')
+
+def extract_summary(instance):
+ # if summary is already specified, use it
+ # if there is no content, there's nothing to do
+ if hasattr(instance, '_summary'):
+ instance.has_summary = True
+ return
+
+ if not instance._content:
+ instance.has_summary = False
+ return
+
+ begin_marker = instance.settings['SUMMARY_BEGIN_MARKER']
+ end_marker = instance.settings['SUMMARY_END_MARKER']
+
+ content = instance._content
+ begin_summary = -1
+ end_summary = -1
+ if begin_marker:
+ begin_summary = content.find(begin_marker)
+ if end_marker:
+ end_summary = content.find(end_marker)
+
+ if begin_summary == -1 and end_summary == -1:
+ instance.has_summary = False
+ return
+
+ # skip over the begin marker, if present
+ if begin_summary == -1:
+ begin_summary = 0
+ else:
+ begin_summary = begin_summary + len(begin_marker)
+
+ if end_summary == -1:
+ end_summary = None
+
+ summary = content[begin_summary:end_summary]
+
+ # remove the markers from the content
+ if begin_summary:
+ content = content.replace(begin_marker, '', 1)
+ if end_summary:
+ content = content.replace(end_marker, '', 1)
+
+ instance._content = content
+ instance._summary = summary
+ instance.has_summary = True
+
+
+def run_plugin(generators):
+ for generator in generators:
+ if isinstance(generator, ArticlesGenerator):
+ for article in generator.articles:
+ extract_summary(article)
+ elif isinstance(generator, PagesGenerator):
+ for page in generator.pages:
+ extract_summary(page)
+
+
+def register():
+ signals.initialized.connect(initialized)
+ try:
+ signals.all_generators_finalized.connect(run_plugin)
+ except AttributeError:
+ # NOTE: This results in #314 so shouldn't really be relied on
+ # https://github.com/getpelican/pelican-plugins/issues/314
+ signals.content_object_init.connect(extract_summary)
diff --git a/infra/website/plugins/summary/test_summary.py b/infra/website/plugins/summary/test_summary.py
new file mode 100755
index 000000000000..c995106155b8
--- /dev/null
+++ b/infra/website/plugins/summary/test_summary.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+
+import unittest
+
+from jinja2.utils import generate_lorem_ipsum
+
+# generate one paragraph, enclosed with <p>
+TEST_CONTENT = str(generate_lorem_ipsum(n=1))
+TEST_SUMMARY = generate_lorem_ipsum(n=1, html=False)
+
+
+from pelican.contents import Page
+
+import summary
+
+class TestSummary(unittest.TestCase):
+ def setUp(self):
+ super(TestSummary, self).setUp()
+
+ summary.register()
+ summary.initialized(None)
+ self.page_kwargs = {
+ 'content': TEST_CONTENT,
+ 'context': {
+ 'localsiteurl': '',
+ },
+ 'metadata': {
+ 'summary': TEST_SUMMARY,
+ 'title': 'foo bar',
+ 'author': 'Blogger',
+ },
+ }
+
+ def _copy_page_kwargs(self):
+ # make a deep copy of page_kwargs
+ page_kwargs = dict([(key, self.page_kwargs[key]) for key in
+ self.page_kwargs])
+ for key in page_kwargs:
+ if not isinstance(page_kwargs[key], dict):
+ break
+ page_kwargs[key] = dict([(subkey, page_kwargs[key][subkey])
+ for subkey in page_kwargs[key]])
+
+ return page_kwargs
+
+ def test_end_summary(self):
+ page_kwargs = self._copy_page_kwargs()
+ del page_kwargs['metadata']['summary']
+ page_kwargs['content'] = (
+ TEST_SUMMARY + '<!-- PELICAN_END_SUMMARY -->' + TEST_CONTENT)
+ page = Page(**page_kwargs)
+ # test both the summary and the marker removal
+ self.assertEqual(page.summary, TEST_SUMMARY)
+ self.assertEqual(page.content, TEST_SUMMARY + TEST_CONTENT)
+
+ def test_begin_summary(self):
+ page_kwargs = self._copy_page_kwargs()
+ del page_kwargs['metadata']['summary']
+ page_kwargs['content'] = (
+ 'FOOBAR<!-- PELICAN_BEGIN_SUMMARY -->' + TEST_CONTENT)
+ page = Page(**page_kwargs)
+ # test both the summary and the marker removal
+ self.assertEqual(page.summary, TEST_CONTENT)
+ self.assertEqual(page.content, 'FOOBAR' + TEST_CONTENT)
+
+ def test_begin_end_summary(self):
+ page_kwargs = self._copy_page_kwargs()
+ del page_kwargs['metadata']['summary']
+ page_kwargs['content'] = (
+ 'FOOBAR<!-- PELICAN_BEGIN_SUMMARY -->' + TEST_SUMMARY +
+ '<!-- PELICAN_END_SUMMARY -->' + TEST_CONTENT)
+ page = Page(**page_kwargs)
+ # test both the summary and the marker removal
+ self.assertEqual(page.summary, TEST_SUMMARY)
+ self.assertEqual(page.content, 'FOOBAR' + TEST_SUMMARY + TEST_CONTENT)