Feat: integrate tag_cloud

This commit is contained in:
Bertrand Benjamin 2020-06-26 10:46:26 +02:00
parent ba64771efb
commit 952d19859c
8 changed files with 306 additions and 59 deletions

View File

@ -42,6 +42,7 @@ PLUGINS = [
'i18n_subsites',
"pelican-page-hierarchy",
"always_modified",
"tag_cloud",
# 'pdf-img',
]
@ -77,6 +78,7 @@ DISPLAY_CATEGORIES_ON_MENU = False
# Sidebar
DISPLAY_PAGES_ON_SIDE = False
TOCTREE = True
TAG_CLOUD = True
#SITELOGO = ""
LINKS = ()

View File

@ -0,0 +1,98 @@
tag_cloud
=========
This plugin generates a tag-cloud.
Installation
------------
In order to use to use this plugin, you have to edit(*) or create(+) the following files::
blog/
├── pelicanconf.py *
├── content
├── plugins +
│ └── tag_cloud.py +
└── themes
└── mytheme
├── templates
│ └── base.html *
└── static
└── css
└── style.css *
In **pelicanconf.py** you have to activate the plugin::
PLUGIN_PATHS = ["plugins"]
PLUGINS = ["tag_cloud"]
Into your **plugins** folder, you should add tag_cloud.py (from this repository).
In your theme files, you should change **base.html** to apply formats (and sizes) defined in **style.css**, as specified in "Settings", below.
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
``TAG_CLOUD_BADGE = True`` Optionnal setting : can bring **badges**, which mean
say : display the number of each tags present
on all articles.
================================================ =====================================================
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 }}
{% if TAG_CLOUD_BADGE %}
<span class="badge">{{ tag.2 }}</span>
{% endif %}
</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.
You should copy/paste this **badge** CSS rule ``ul.tagcloud .list-group-item <span>.badge``
if you're using ``TAG_CLOUD_BADGE`` setting. (this rule, potentially long , is suggested to avoid
conflicts with CSS libs as twitter Bootstrap)
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%;
}
/* ... add li.tag-3 etc, as much as needed */
ul.tagcloud .list-group-item span.badge {
background-color: grey;
color: white;
}
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).

View File

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

View File

@ -0,0 +1,90 @@
'''
tag_cloud
===================================
This plugin generates a tag cloud from available tags
'''
from __future__ import unicode_literals
from collections import defaultdict
from operator import itemgetter
import logging
import math
import random
from pelican import signals
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')
settings.setdefault('TAG_CLOUD_BADGE', False)
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 = tags[0]
min_count = tags[-1]
steps = generator.settings.get('TAG_CLOUD_STEPS')
# calculate word sizes
def generate_tag(tag, count):
tag = (
tag,
int(math.floor(steps - (steps - 1) * math.log(count - min_count + 1)
/ (math.log(max_count - min_count + 1) or 1)))
)
if generator.settings.get('TAG_CLOUD_BADGE'):
tag += (count,)
return tag
tag_cloud = [
generate_tag(tag, count)
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)

View File

@ -87,7 +87,7 @@ aside {
color: @sidebar-link-hover-color;
}
div {
.title {
text-align: center;
margin-bottom: 50px;
margin-top: 50px;
@ -110,59 +110,95 @@ aside {
}
nav {
ul {
padding-inline-start: 0px;
display: block;
}
ul.toctree {
li {
a {
background-color: @navbar-bg;
color: @navbar-text-color;
border: none;
}
}
li.toctree-l1 {
li.current{
background-color: @navbar-toctree-l2-sel-bg;
color: @navbar-toctree-l2-sel-txt;
padding: 10px;
}
}
li.current{
a {
background-color: @navbar-toctree-l1-sel-bg;
border-bottom: solid 1px @light-grey;
border-left: solid 2px @grey;
color: @navbar-toctree-l1-sel-txt;
}
a:hover {
color: @orange;
}
}
li.toctree-l2 {
a {
border: none;
background-color: @navbar-toctree-l2-bg;
color: @navbar-toctree-l2-txt;
}
}
a {
padding: 10px;
}
a:hover {
color: @orange;
}
}
ul.list {
li {
display: inline;
line-height: 1.6em;
font-size: 1.28em;
text-transform: lowercase;
}
}
}
ul {
padding-inline-start: 0px;
display: block;
}
ul.toctree {
li {
a {
background-color: @navbar-bg;
color: @navbar-text-color;
border: none;
}
}
li.toctree-l1 {
li.current{
background-color: @navbar-toctree-l2-sel-bg;
color: @navbar-toctree-l2-sel-txt;
padding: 10px;
}
}
li.current{
a {
background-color: @navbar-toctree-l1-sel-bg;
border-bottom: solid 1px @light-grey;
border-left: solid 2px @grey;
color: @navbar-toctree-l1-sel-txt;
}
a:hover {
color: @orange;
}
}
li.toctree-l2 {
a {
border: none;
background-color: @navbar-toctree-l2-bg;
color: @navbar-toctree-l2-txt;
}
}
a {
padding: 10px;
}
a:hover {
color: @orange;
}
}
ul.list {
li {
display: inline;
line-height: 1.6em;
font-size: 1.28em;
text-transform: lowercase;
}
}
}
.tagcloud {
h2 {
background-color: @sidebar-bg;
margin-bottom: 0;
}
ul {
list-style: none;
padding: 0;
}
ul li {
display: inline-block;
}
li.tag-0 {
font-size: 170%;
}
li.tag-1 {
font-size: 150%;
}
li.tag-2 {
font-size: 120%;
}
li.tag-3 {
font-size: 100%;
}
li.tag-4 {
font-size: 80%;
}
}
}
main {

File diff suppressed because one or more lines are too long

View File

@ -70,7 +70,7 @@
</head>
<body>
<aside>
<div>
<div class="title">
<!--
<a href="{{ SITEURL }}">
{% if SITELOGO %}
@ -86,9 +86,9 @@
</div>
<nav>
{% if TOCTREE %}
{% if TOCTREE %}
{% include "partial/toctree.html" %}
{% endif %}
{% endif %}
{% if pages or LINKS%}
<ul class="list">
@ -106,8 +106,12 @@
{% endfor %}
</ul>
{% endif %}
</nav>
{% if TAG_CLOUD %}
{% include "partial/tagcloud.html" %}
{% endif %}
</aside>
<main>
{% if MAIN_MENU %}

View File

@ -0,0 +1,15 @@
<div class="tagcloud">
<h2>Thèmes</h2>
<ul>
{% for tag in tag_cloud %}
<li class="tag-{{ tag.1 }}">
<a href="{{ SITEURL }}/{{ tag.0.url }}">
{{ tag.0 }}
{% if TAG_CLOUD_BADGE %}
<span class="badge">{{ tag.2 }}</span>
{% endif %}
</a>
</li>
{% endfor %}
</ul>
</div>