Quellcode durchsuchen

break out tag_cloud from core into plugin

winlu vor 9 Jahren
Ursprung
Commit
edfd3365af

+ 0 - 3
.gitmodules

@@ -46,9 +46,6 @@
 [submodule "pandoc_reader"]
 	path = pandoc_reader
 	url = https://github.com/liob/pandoc_reader.git
-[submodule "sort_tags"]
-	path = sort_tags
-	url = https://github.com/ingwinlu/sort_tags.git
 [submodule "bootstrapify"]
 	path = bootstrapify
 	url = https://github.com/ingwinlu/pelican-bootstrapify.git

+ 2 - 2
Readme.rst

@@ -156,14 +156,14 @@ Simple footnotes          Adds footnotes to blog posts
 
 Sitemap                   Generates plain-text or XML sitemaps
 
-sort_tags                 Provides `tags_sorted_by_article_length` to templates, which contains all tags, sorted by how many articles it contains first, and alphabetically second.
-
 Static comments           Allows you to add static comments to an article
 
 Subcategory               Adds support for subcategories
 
 Summary                   Allows easy, variable length summaries directly embedded into the body of your articles
 
+tag_cloud                 Provides a tag_cloud
+
 Thumbnailer               Creates thumbnails for all of the images found under a specific directory
 
 Tipue Search              Serializes generated HTML to JSON that can be used by jQuery plugin - Tipue Search

+ 0 - 1
sort_tags

@@ -1 +0,0 @@
-Subproject commit a3413a417ede463a66e59c5ea1ea017ff7782b84

+ 52 - 0
tag_cloud/README.rst

@@ -0,0 +1,52 @@
+tag_cloud
+=========
+
+This plugin generates a tag-cloud.
+
+Settings
+--------
+
+================================================    =====================================================
+Setting name (followed by default value)            What does it do?
+================================================    =====================================================
+``TAG_CLOUD_STEPS = 4``                             Count of different font sizes in the tag
+                                                    cloud.
+``TAG_CLOUD_MAX_ITEMS = 100``                       Maximum number of tags in the cloud.
+``TAG_CLOUD_SORTING = 'random'``                    The tag cloud ordering scheme.  Valid values:
+                                                    random, alphabetically, alphabetically-rev, size and
+                                                    size-rev
+================================================    =====================================================
+
+The default theme does not include a tag cloud, but it is pretty easy to add one::
+
+    <ul class="tagcloud">
+        {% for tag in tag_cloud %}
+            <li class="tag-{{ tag.1 }}"><a href="{{ SITEURL }}/{{ tag.0.url }}">{{ tag.0 }}</a></li>
+        {% endfor %}
+    </ul>
+
+You should then also define CSS styles with appropriate classes (tag-1 to tag-N,
+where N matches ``TAG_CLOUD_STEPS``), tag-1 being the most frequent, and
+define a ``ul.tagcloud`` class with appropriate list-style to create the cloud.
+For example::
+
+    ul.tagcloud {
+      list-style: none;
+        padding: 0;
+    }
+
+    ul.tagcloud li {
+        display: inline-block;
+    }
+
+    li.tag-1 {
+        font-size: 150%;
+    }
+
+    li.tag-2 {
+        font-size: 120%;
+    }
+
+    ...
+
+By default the tags in the cloud are sorted randomly, but if you prefers to have it alphabetically use the `alphabetically` (ascending) and `alphabetically-rev` (descending). Also is possible to sort the tags by it's size (number of articles with this specific tag) using the values `size` (ascending) and `size-rev` (descending).

+ 2 - 0
tag_cloud/__init__.py

@@ -0,0 +1,2 @@
+from .tag_cloud import *
+

+ 78 - 0
tag_cloud/tag_cloud.py

@@ -0,0 +1,78 @@
+'''
+tag_cloud
+===================================
+
+This plugin generates a tag cloud from available tags
+'''
+from __future__ import unicode_literals
+
+from collections import defaultdict
+from operator import attrgetter, itemgetter
+
+import logging
+import math
+import random
+
+from pelican import signals, contents
+
+logger = logging.getLogger(__name__)
+
+def set_default_settings(settings):
+    settings.setdefault('TAG_CLOUD_STEPS', 4)
+    settings.setdefault('TAG_CLOUD_MAX_ITEMS', 100)
+    settings.setdefault('TAG_CLOUD_SORTING', 'random')
+
+def init_default_config(pelican):
+    from pelican.settings import DEFAULT_CONFIG
+    set_default_settings(DEFAULT_CONFIG)
+    if(pelican):
+           set_default_settings(pelican.settings)
+
+def generate_tag_cloud(generator):
+    tag_cloud = defaultdict(int)
+    for article in generator.articles:
+        for tag in getattr(article, 'tags', []):
+            tag_cloud[tag] += 1
+
+    tag_cloud = sorted(tag_cloud.items(), key=itemgetter(1), reverse=True)
+    tag_cloud = tag_cloud[:generator.settings.get('TAG_CLOUD_MAX_ITEMS')]
+
+    tags = list(map(itemgetter(1), tag_cloud))
+    if tags:
+        max_count = max(tags)
+    steps = generator.settings.get('TAG_CLOUD_STEPS')
+
+    # calculate word sizes
+    tag_cloud = [
+        (
+            tag,
+            int(math.floor(steps - (steps - 1) * math.log(count)
+                / (math.log(max_count)or 1)))
+        )
+        for tag, count in tag_cloud
+    ]
+
+    sorting = generator.settings.get('TAG_CLOUD_SORTING')
+
+    if sorting == 'alphabetically':
+        tag_cloud.sort(key=lambda elem: elem[0].name)
+    elif sorting == 'alphabetically-rev':
+        tag_cloud.sort(key=lambda elem: elem[0].name, reverse=True)
+    elif sorting == 'size':
+        tag_cloud.sort(key=lambda elem: elem[1])
+    elif sorting == 'size-rev':
+        tag_cloud.sort(key=lambda elem: elem[1], reverse=True)
+    elif sorting == 'random':
+        random.shuffle(tag_cloud)
+    else:
+        logger.warning("setting for TAG_CLOUD_SORTING not recognized: %s, "
+                       "falling back to 'random'", sorting)
+        random.shuffle(tag_cloud)
+
+    #make available in context
+    generator.tag_cloud = tag_cloud
+    generator._update_context(['tag_cloud'])
+
+def register():
+    signals.initialized.connect(init_default_config)
+    signals.article_generator_finalized.connect(generate_tag_cloud)

+ 4 - 0
tag_cloud/test_data/article_1.md

@@ -0,0 +1,4 @@
+Title: Article1
+tags: fun, pelican, plugins
+
+content, yeah!

+ 5 - 0
tag_cloud/test_data/article_2.md

@@ -0,0 +1,5 @@
+Title: Article2
+tags: pelican, plugins, python
+
+content2, yeah!
+

+ 84 - 0
tag_cloud/test_tag_cloud.py

@@ -0,0 +1,84 @@
+import unittest, os, sys
+import six
+import tag_cloud
+
+from pelican.generators import ArticlesGenerator
+from pelican.tests.support import get_settings
+from pelican.urlwrappers import Tag
+
+CUR_DIR = os.path.dirname(__file__)
+CONTENT_DIR = os.path.join(CUR_DIR, 'test_data')
+
+class TestTagCloudGeneration(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        cls._settings = get_settings(filenames={})
+        cls._settings['DEFAULT_CATEGORY'] = 'Default'
+        cls._settings['DEFAULT_DATE'] = (1970, 1, 1)
+        cls._settings['READERS'] = {'asc': None}
+        cls._settings['CACHE_CONTENT'] = False
+        tag_cloud.set_default_settings(cls._settings)
+
+        cls.generator = ArticlesGenerator(
+            context=cls._settings.copy(), settings=cls._settings,
+            path=CONTENT_DIR, theme=cls._settings['THEME'], output_path=None)
+        cls.generator.generate_context()
+
+
+    def test_tag_cloud_random(self):
+        tag_cloud.generate_tag_cloud(self.generator)
+        expected = [
+                (Tag('plugins', self._settings), 1),
+                (Tag('fun', self._settings), 4),
+                (Tag('python', self._settings), 4),
+                (Tag('pelican', self._settings), 1)
+            ]
+        six.assertCountEqual(self, self.generator.tag_cloud, expected)
+
+    def test_tag_cloud_alphabetical(self):
+        self.generator.settings['TAG_CLOUD_SORTING'] = 'alphabetically'
+        tag_cloud.generate_tag_cloud(self.generator)
+        expected = [
+                (Tag('fun', self._settings), 4),
+                (Tag('pelican', self._settings), 1),
+                (Tag('plugins', self._settings), 1),
+                (Tag('python', self._settings), 4)
+            ]
+        self.assertEqual(self.generator.tag_cloud, expected)
+    
+    def test_tag_cloud_alphabetical_rev(self):
+        self.generator.settings['TAG_CLOUD_SORTING'] = 'alphabetically-rev'
+        tag_cloud.generate_tag_cloud(self.generator)
+        expected = [
+                (Tag('python', self._settings), 4),
+                (Tag('plugins', self._settings), 1),
+                (Tag('pelican', self._settings), 1),
+                (Tag('fun', self._settings), 4)
+            ]
+        self.assertEqual(self.generator.tag_cloud, expected)
+
+    def test_tag_cloud_size(self):
+        self.generator.settings['TAG_CLOUD_SORTING'] = 'size'
+        tag_cloud.generate_tag_cloud(self.generator)
+        expected = [
+                (Tag('pelican', self._settings), 1),
+                (Tag('plugins', self._settings), 1),
+                (Tag('fun', self._settings), 4),
+                (Tag('python', self._settings), 4)
+            ]
+        self.assertEqual(self.generator.tag_cloud, expected)
+
+    def test_tag_cloud_size_rev(self):
+        self.generator.settings['TAG_CLOUD_SORTING'] = 'size-rev'
+        tag_cloud.generate_tag_cloud(self.generator)
+        expected = [
+                (Tag('fun', self._settings), 4),
+                (Tag('python', self._settings), 4),
+                (Tag('pelican', self._settings), 1),
+                (Tag('plugins', self._settings), 1)
+            ]
+        self.assertEqual(self.generator.tag_cloud, expected)
+
+if __name__ == "__main__":
+    unittest.main()