"Sexual Dimorphism": category of personal identity, into conclusion
[Ultimately_Untrue_Thought.git] / plugins / tag_cloud.py
1 # from https://github.com/getpelican/pelican-plugins as of f4d717ff
2
3 # but with a fix to the alphabetical sorting
4
5 '''
6 tag_cloud
7 ===================================
8
9 This plugin generates a tag cloud from available tags
10 '''
11 from __future__ import unicode_literals
12
13 from collections import defaultdict
14 from operator import itemgetter
15
16 import logging
17 import math
18 import random
19
20 from pelican import signals
21
22 logger = logging.getLogger(__name__)
23
24
25 def set_default_settings(settings):
26     settings.setdefault('TAG_CLOUD_STEPS', 4)
27     settings.setdefault('TAG_CLOUD_MAX_ITEMS', 100)
28     settings.setdefault('TAG_CLOUD_SORTING', 'random')
29     settings.setdefault('TAG_CLOUD_BADGE', False)
30
31
32 def init_default_config(pelican):
33     from pelican.settings import DEFAULT_CONFIG
34     set_default_settings(DEFAULT_CONFIG)
35     if(pelican):
36             set_default_settings(pelican.settings)
37
38
39 def alphabetic_sort_key(element):
40     tag = element[0].name
41     if tag[0] == "æ":  # exceptional case
42         return "ae"+tag[1:]
43     # `.lower()` to avoid putting all uppercase tags lexicographically
44     # before lowercase tags —ZMD
45     return tag.lower()
46
47
48 def generate_tag_cloud(generator):
49     tag_cloud = defaultdict(int)
50     for article in generator.articles:
51         for tag in getattr(article, 'tags', []):
52             tag_cloud[tag] += 1
53
54     tag_cloud = sorted(tag_cloud.items(), key=itemgetter(1), reverse=True)
55     tag_cloud = tag_cloud[:generator.settings.get('TAG_CLOUD_MAX_ITEMS')]
56
57     tags = list(map(itemgetter(1), tag_cloud))
58     if tags:
59         max_count = max(tags)
60     steps = generator.settings.get('TAG_CLOUD_STEPS')
61
62     # calculate word sizes
63     def generate_tag(tag, count):
64         tag = (
65             tag,
66             int(math.floor(steps - (steps - 1) * math.log(count)
67                 / (math.log(max_count)or 1)))
68         )
69         if generator.settings.get('TAG_CLOUD_BADGE'):
70             tag += (count,)
71         return tag
72
73     tag_cloud = [
74         generate_tag(tag, count)
75         for tag, count in tag_cloud
76     ]
77
78     sorting = generator.settings.get('TAG_CLOUD_SORTING')
79
80     if sorting == 'alphabetically':
81         tag_cloud.sort(key=alphabetic_sort_key)
82     elif sorting == 'alphabetically-rev':
83         tag_cloud.sort(key=lambda elem: elem[0].name, reverse=True)
84     elif sorting == 'size':
85         tag_cloud.sort(key=lambda elem: elem[1])
86     elif sorting == 'size-rev':
87         tag_cloud.sort(key=lambda elem: elem[1], reverse=True)
88     elif sorting == 'random':
89         random.shuffle(tag_cloud)
90     else:
91         logger.warning("setting for TAG_CLOUD_SORTING not recognized: %s, "
92                        "falling back to 'random'", sorting)
93         random.shuffle(tag_cloud)
94
95     # make available in context
96     generator.tag_cloud = tag_cloud
97     generator._update_context(['tag_cloud'])
98
99
100 def register():
101     signals.initialized.connect(init_default_config)
102     signals.article_generator_finalized.connect(generate_tag_cloud)