Commit 4e2752ef authored by BorisPAING's avatar BorisPAING

Amélioration structure du blog

parent b044937b
......@@ -2,7 +2,9 @@ Title: Qui sommes-nous ?
Order: 9
Date: 2017-03-27
Slug: qui-sommes-nous
name: about
Authors: cgeek
Lang: fr
Nous sommes de simples citoyens, principalement français, s'efforçant de produire une nouvelle valeur économique appelée « *monnaie libre* », de forme numérique, et respectant les principes établis par la [Théorie Relative de la Monnaie (TRM)](http://trm.creationmonetaire.info/).
......
This diff is collapsed.
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).
'''
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)
Title: Article1
tags: fun, pelican, plugins
content, yeah!
\ No newline at end of file
Title: Article2
tags: pelican, plugins, python
content2, yeah!
Title: Article3
tags: pelican, plugins
content3, yeah!
Title: Article4
tags: pelican, fun
content4, yeah!
Title: Article5
tags: plugins, pelican, fun
content5, yeah!
import unittest
import os
import six
import tag_cloud
from shutil import rmtree
from tempfile import mkdtemp
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.temp_path = mkdtemp(prefix='pelicantests.')
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)
context = cls._settings.copy()
context['generated_content'] = dict()
context['static_links'] = set()
cls.generator = ArticlesGenerator(
context=context, settings=cls._settings,
path=CONTENT_DIR, theme=cls._settings['THEME'], output_path=cls.temp_path)
cls.generator.generate_context()
@classmethod
def tearDownClass(cls):
rmtree(cls.temp_path)
def test_tag_cloud_random(self):
self.generator.settings['TAG_CLOUD_STEPS'] = 10
self.generator.settings['TAG_CLOUD_BADGE'] = False
tag_cloud.generate_tag_cloud(self.generator)
expected = [
(Tag('pelican', self._settings), 1),
(Tag('plugins', self._settings), 2),
(Tag('fun', self._settings), 3),
(Tag('python', self._settings), 10)
]
six.assertCountEqual(self, self.generator.tag_cloud, expected)
def test_tag_cloud_badge(self):
self.generator.settings['TAG_CLOUD_STEPS'] = 10
self.generator.settings['TAG_CLOUD_BADGE'] = True
tag_cloud.generate_tag_cloud(self.generator)
expected = [
(Tag('pelican', self._settings), 1, 5),
(Tag('plugins', self._settings), 2, 4),
(Tag('fun', self._settings), 3, 3),
(Tag('python', self._settings), 10, 1)
]
six.assertCountEqual(self, self.generator.tag_cloud, expected)
def test_tag_cloud_alphabetical(self):
self.generator.settings['TAG_CLOUD_STEPS'] = 10
self.generator.settings['TAG_CLOUD_SORTING'] = 'alphabetically'
tag_cloud.generate_tag_cloud(self.generator)
expected = [
(Tag('fun', self._settings), 3),
(Tag('pelican', self._settings), 1),
(Tag('plugins', self._settings), 2),
(Tag('python', self._settings), 10)
]
self.assertEqual(self.generator.tag_cloud, expected)
def test_tag_cloud_alphabetical_rev(self):
self.generator.settings['TAG_CLOUD_STEPS'] = 10
self.generator.settings['TAG_CLOUD_SORTING'] = 'alphabetically-rev'
tag_cloud.generate_tag_cloud(self.generator)
expected = [
(Tag('python', self._settings), 10),
(Tag('plugins', self._settings), 2),
(Tag('pelican', self._settings), 1),
(Tag('fun', self._settings), 3)
]
self.assertEqual(self.generator.tag_cloud, expected)
def test_tag_cloud_size(self):
self.generator.settings['TAG_CLOUD_STEPS'] = 10
self.generator.settings['TAG_CLOUD_SORTING'] = 'size'
tag_cloud.generate_tag_cloud(self.generator)
expected = [
(Tag('pelican', self._settings), 1),
(Tag('plugins', self._settings), 2),
(Tag('fun', self._settings), 3),
(Tag('python', self._settings), 10)
]
self.assertEqual(self.generator.tag_cloud, expected)
def test_tag_cloud_size_rev(self):
self.generator.settings['TAG_CLOUD_STEPS'] = 10
self.generator.settings['TAG_CLOUD_SORTING'] = 'size-rev'
tag_cloud.generate_tag_cloud(self.generator)
expected = [
(Tag('python', self._settings), 10),
(Tag('fun', self._settings), 3),
(Tag('plugins', self._settings), 2),
(Tag('pelican', self._settings), 1)
]
self.assertEqual(self.generator.tag_cloud, expected)
if __name__ == "__main__":
unittest.main()
......@@ -85,6 +85,83 @@ nav a {
border: 0;
}
/* ====== Sidebar ====== */
#sidebar {
position: sticky;
top: 88px;
section {
background: #f7f7f7;
padding: 1em 15px;
border: 1px solid #e5e5e5;
border-radius: 1em;
margin-bottom: 1em;
h4 {
font-size: 1.5em;
margin-bottom: 1em;
margin-top: 0;
a {
border: 0;
text-decoration: none;
}
}
> h4:first-child {
padding-top: 0;
margin-top: 0;
}
ul {
list-style-type: none;
padding-left: 0;
li {
font-family: Sans-Serif;
margin: 1em 0;
a {
border-bottom: 0;
font-weight: 500;
font-size: 1em;
}
time {
font-size: 0.9em;
font-weight: 300;
opacity: 0.7;
}
}
}
&#tags {
text-align: justify;
ul {
li {
display: inline;
}
}
}
}
}
/* ====== Breadcrumbs ====== */
......@@ -621,7 +698,11 @@ body > footer div {
&> * {
display: flex;
flex-direction: column;
align-items: center;
@media (max-width:575px) {
flex-basis: calc(50% - 2em);
......@@ -640,7 +721,22 @@ body > footer div {
flex-basis: 100%;
flex-shrink: 0;
}
&#about {
h5 {
display: none;
}
ul {
list-style-type: none;
padding-left: 0;
margin-left: 0;
}
}
p.back-to-top {
a:before {
......@@ -650,13 +746,17 @@ body > footer div {
}
}
&.navbar-search {
input {
&.search-bar {
margin: 0;
input#tipue_search_input {
padding-top: 0;
padding-bottom: 0;
height: 3em;
padding-top: 0.5em;
padding-bottom: 0.5em;
padding-left: 40px;
padding-right: 0.5em;
height: 3em;
}
}
......
......@@ -51,23 +51,29 @@
<link rel="canonical" href="{{ SITEURL }}/{{ article.url }}">
{% endblock %}
{% block breadcrumbs %}
{% if DISPLAY_BREADCRUMBS %}
{% if DISPLAY_CATEGORY_IN_BREADCRUMBS %}
<ol class="breadcrumb">
<li><a href="{{ SITEURL }}" title="{{ SITENAME }}"><i class="fa fa-home fa-lg"></i></a></li>
<li><a href="{{ SITEURL }}/{{ article.category.url }}" title="{{ article.category }}">{{ article.category }}</a></li>
<li class="active">{{ article.title }}</li>
</ol>
{% else %}
<ol class="breadcrumb">
<li><a href="{{ SITEURL }}" title="{{ SITENAME }}"><i class="fa fa-home fa-lg"></i></a></li>
<li class="active">{{ article.title }}</li>
<li><a href="{{ SITEURL }}" title="{{ SITENAME }}"><i class="fa fa-home fa-lg"></i></a></li>
<li><a href="{{ SITEURL}}/{{ INDEX_URL }}">{{ _('Actualités') }}</a></li>
{% if DISPLAY_CATEGORY_IN_BREADCRUMBS %}
<li><a href="{{ SITEURL }}/{{ article.category.url }}" title="{{ article.category }}">{{ article.category }}</a></li>
{% endif %}
<li class="active">{{ article.title }}</li>
</ol>
{% endif %}
{% endif %}
{% endblock %}
{% block content %}
<section id="content">
<article>
......
{% extends "base.html" %}
{% block title %}{{ _('Catégories') }} - _('Actualités') }} - {{ SITENAME }}{% endblock %}
{% block breadcrumbs %}
{% if DISPLAY_BREADCRUMBS %}
<ol class="breadcrumb">
<li><a href="{{ SITEURL }}" title="{{ SITENAME }}"><i class="fa fa-home fa-lg"></i></a></li>
<li><a href="{{ SITEURL}}/{{ INDEX_URL }}">{{ _('Actualités') }}</a></li>
<li class="active">{{ _('Catégories') }}</li>
</ol>
{% endif %}
{% endblock %}
{% block content %}
<section id="categories">
<h1>{{ _('Catégories') }} {{ SITENAME }}</h1>
<div class="panel-group" id="accordion">
{% for category, articles in categories %}
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapse-{{category.slug}}">{{ category }} <span class="badge pull-right">{{ articles|count }}</span></a>
</h4>
</div>
<div id="collapse-{{category.slug}}" class="panel-collapse collapse">
<div class="panel-body">
{% for article in articles %}
<p><span class="categories-timestamp"><time datetime="{{ article.date.isoformat() }}">{{ article.locale_date }}</time></span> <a href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}</a></p>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>
</section>
{% endblock %}
{% extends "article_list.html" %}
{% block title %}{{ category }} - {{ _('Actualités') }} - {{ SITENAME }}{% endblock %}
{% block meta %}
<meta name="author" content="{{ AUTHOR }}" />
<meta name="keywords" content="{{ category }}" />
{% endblock %}
{% block breadcrumbs %}
{% if DISPLAY_BREADCRUMBS %}
<ol class="breadcrumb">
<li><a href="{{ SITEURL }}" title="{{ SITENAME }}"><i class="fa fa-home fa-lg"></i></a></li>
<li><a href="{{ SITEURL}}/{{ INDEX_URL }}">{{ _('Actualités') }}</a></li>
<li class="active">{{ category }}</li>
</ol>
{% endif %}
{% endblock %}
......@@ -23,7 +23,7 @@
<footer class="container{% if BOOTSTRAP_FLUID %}-fluid{% endif %}">
<div>
{% if 'tipue_search' in PLUGINS %}
<form class="navbar-search" action="{{ SEARCH_URL | default('/search.html') }}">
<form class="search-bar navbar-search" action="{{ SEARCH_URL | default('/search.html') }}">
<h5>Rechercher un contenu</h5>
<input type="text" class="search-query" placeholder="{{ _('Rechercher') }}" name="q" id="tipue_search_input" required>
......@@ -96,19 +96,32 @@
{% endif %}
{% for thisLang in AVAILABLE_LANGS %}
<li><a href="{{ main_siteurl }}/{{ thisLang }}/">{{ thisLang }}</a></li>
{% endfor %}
{#
<li><a href="{{ SITEURL }}/{{ translation.url }}">{{ translation.lang }}</a></li>
{% endfor %}
{% elif %}
<li><a href="{{ SITEURL }}/{{ translation.url }}">{{ translation.lang }}</a></li>
{% set translationIsFound = false %}
{# ne fonctionne pas ("CRITICAL: KeyError: [...]")
{% for thisTranslation in translations %}
{% if thisTranslation.lang == thisLang %}
{% set translationIsFound = true %}
<li><a href="{{ SITEURL }}/{{ thisTranslation.url }}">{{ thisTranslation.lang }}</a></li>
{% endif %}
{% endfor %}
{% else %}
#}
{% if not translationIsFound %}
<li><a href="{{ main_siteurl }}/{{ thisLang }}/">{{ thisLang }}</a></li>
{% endif %}
#}
{% endfor %}
</ul>
</nav>
......
<!-- Sidebar -->
<section class="well well-sm">
<ul class="list-group list-group-flush">
{% include 'includes/sidebar/recent_posts.html' %}
{% include 'includes/sidebar/tag_cloud.html' %}
{% include 'includes/sidebar/show_source.html' %}
{% include 'includes/sidebar/series.html' %}
{% include 'includes/sidebar/authors.html' %}
{% include 'includes/sidebar/images.html' %}
</ul>
</section>
{% if article %}
{% include 'includes/sidebar/recent_posts.html' %}
{% elif category %}
{% include 'includes/sidebar/tag_cloud.html' %}