tag_cloud.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. '''
  2. tag_cloud
  3. ===================================
  4. This plugin generates a tag cloud from available tags
  5. '''
  6. from __future__ import unicode_literals
  7. from collections import defaultdict
  8. from operator import itemgetter
  9. import logging
  10. import math
  11. import random
  12. from pelican import signals
  13. logger = logging.getLogger(__name__)
  14. def set_default_settings(settings):
  15. settings.setdefault('TAG_CLOUD_STEPS', 4)
  16. settings.setdefault('TAG_CLOUD_MAX_ITEMS', 100)
  17. settings.setdefault('TAG_CLOUD_SORTING', 'random')
  18. settings.setdefault('TAG_CLOUD_BADGE', False)
  19. def init_default_config(pelican):
  20. from pelican.settings import DEFAULT_CONFIG
  21. set_default_settings(DEFAULT_CONFIG)
  22. if(pelican):
  23. set_default_settings(pelican.settings)
  24. def generate_tag_cloud(generator):
  25. tag_cloud = defaultdict(int)
  26. for article in generator.articles:
  27. for tag in getattr(article, 'tags', []):
  28. tag_cloud[tag] += 1
  29. tag_cloud = sorted(tag_cloud.items(), key=itemgetter(1), reverse=True)
  30. tag_cloud = tag_cloud[:generator.settings.get('TAG_CLOUD_MAX_ITEMS')]
  31. tags = list(map(itemgetter(1), tag_cloud))
  32. if tags:
  33. max_count = tags[0]
  34. min_count = tags[-1]
  35. steps = generator.settings.get('TAG_CLOUD_STEPS')
  36. # calculate word sizes
  37. def generate_tag(tag, count):
  38. tag = (
  39. tag,
  40. int(math.floor(steps - (steps - 1) * math.log(count - min_count + 1)
  41. / (math.log(max_count - min_count + 1) or 1)))
  42. )
  43. if generator.settings.get('TAG_CLOUD_BADGE'):
  44. tag += (count,)
  45. return tag
  46. tag_cloud = [
  47. generate_tag(tag, count)
  48. for tag, count in tag_cloud
  49. ]
  50. sorting = generator.settings.get('TAG_CLOUD_SORTING')
  51. if sorting == 'alphabetically':
  52. tag_cloud.sort(key=lambda elem: elem[0].name)
  53. elif sorting == 'alphabetically-rev':
  54. tag_cloud.sort(key=lambda elem: elem[0].name, reverse=True)
  55. elif sorting == 'size':
  56. tag_cloud.sort(key=lambda elem: elem[1])
  57. elif sorting == 'size-rev':
  58. tag_cloud.sort(key=lambda elem: elem[1], reverse=True)
  59. elif sorting == 'random':
  60. random.shuffle(tag_cloud)
  61. else:
  62. logger.warning("setting for TAG_CLOUD_SORTING not recognized: %s, "
  63. "falling back to 'random'", sorting)
  64. random.shuffle(tag_cloud)
  65. # make available in context
  66. generator.tag_cloud = tag_cloud
  67. generator._update_context(['tag_cloud'])
  68. def register():
  69. signals.initialized.connect(init_default_config)
  70. signals.article_generator_finalized.connect(generate_tag_cloud)