diff --git a/.gitignore b/.gitignore index 29ac491f..721af351 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,8 @@ .*.swp .*.swo *.pyc +docs/_build +docs/fr/_build +build +dist +output diff --git a/README.rst b/README.rst index 71d94290..5cf557fa 100644 --- a/README.rst +++ b/README.rst @@ -32,8 +32,7 @@ Heh, you didn't noticed? "Pelican" is an anagram for "Calepin" ;) Source code ----------- -You can access the source code via mercurial at http://hg.notmyidea.org/pelican/ -or via git on http://github.com/ametaireau/pelican/ +You can access the source code via git on http://github.com/ametaireau/pelican/ If you feel hackish, have a look to the `pelican's internals explanations `_. diff --git a/THANKS b/THANKS index 0604e5db..078a67d1 100644 --- a/THANKS +++ b/THANKS @@ -10,3 +10,7 @@ bugs or giving ideas. Thanks to them ! - David Kulak - Arnaud Bos - nblock (Florian) +- Bruno Bord +- Laureline Guérin +- Samuel Martin +- Marcus Fredriksson diff --git a/docs/conf.py b/docs/conf.py index 0efe92b2..507e30a3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -8,12 +8,15 @@ import sys, os # -- General configuration ----------------------------------------------------- templates_path = ['_templates'] +extensions = ['sphinx.ext.autodoc',] source_suffix = '.rst' master_doc = 'index' project = u'Pelican' -copyright = u'2010, Alexis Metaireau' +copyright = u'2010, Alexis Metaireau and contributors' exclude_patterns = ['_build'] pygments_style = 'sphinx' +version = "2" +release = version # -- Options for HTML output --------------------------------------------------- diff --git a/docs/faq.rst b/docs/faq.rst new file mode 100644 index 00000000..bee1dd54 --- /dev/null +++ b/docs/faq.rst @@ -0,0 +1,38 @@ +Frequently Asked Questions (FAQ) +################################ + +Here is a summary of the frequently asked questions for pelican. + +Is it mandatory to have a configuration file ? +============================================== + +No, it's not. Configurations files are just an easy way to configure pelican. +For the basic operations, it's possible to specify options while invoking +pelican with the command line (see `pelican --help` for more informations about +that) + +I'm creating my own theme, how to use pygments ? +================================================ + +Pygment add some classes to the generated content, so the theming of your theme +will be done thanks to a css file. You can have a look to the one proposed by +default `on the project website `_ + +How do I create my own theme ? +============================== + +Please refer yourself to :ref:`theming-pelican`. + +How can I help ? +================ + +You have different options to help. First, you can use pelican, and report any +idea or problem you have on `the bugtracker +`_. + +If you want to contribute, please have a look to `the git repository +`_, fork it, add your changes and do +a pull request, I'll review them as soon as possible. + +You can also contribute by creating themes, and making the documentation +better. diff --git a/docs/fr/astuces.rst b/docs/fr/astuces.rst new file mode 100644 index 00000000..3f9a3987 --- /dev/null +++ b/docs/fr/astuces.rst @@ -0,0 +1,20 @@ +Trucs et astuces pour Pelican +############################# + +Personnaliser l'url d'un article pour Pelican +============================================= + +Par défaut, quand vous créez un article ayant pour titre *Mon article pour Pelican*, +l'url par défaut devient *mon-article-pour-pelican.html*. Cependant, il est possible +de modifier cela en utilisant la technique utilisée pour les traductions d'article, +c'est à dire le paramètre *:slug:* :: + + Mon article pour Pelican + ######################## + + :date: 2011-01-31 11:05 + :slug: super-article-pour-pelican + + bla, bla, bla … + +En prenant cet exemple ci dessus, votre url deviendra *super-article-pour-pelican.html* diff --git a/docs/fr/bases.rst b/docs/fr/bases.rst new file mode 100644 index 00000000..7a6fd118 --- /dev/null +++ b/docs/fr/bases.rst @@ -0,0 +1,58 @@ +Les bases de Pelican +#################### + +Créer son premier article +========================= + +Pour créer notre premier article, nous allons éditer un fichier, par exemple premier_article.rst :: + + Premier article pour Pelican + ############################ + :author: Guillaume + :date: 2011-01-08 10:20 + :category: GNU-Linux + :tags: tutoriel, git + Ceci est un tutoriel pour configurer git. + Bla, bla, bla .... + +Maintenant que ce fichier est créé, on va lancer la création du blog :: + + pelican . + +Vous aller obtenir une sortie comme celle ci — $PATH représente le dossier où vous +avez créé votre article :: + + [ok] writing $PATH/output/feeds/all.atom.xml + [ok] writing $PATH/output/feeds/GNU/Linux.atom.xml + [ok] writing $PATH/output/feeds/all-en.atom.xml + [ok] writing $PATH/output/premier-article-pour-pelican.html + [ok] writing $PATH/output/index.html + [ok] writing $PATH/output/tags.html + [ok] writing $PATH/output/categories.html + [ok] writing $PATH/output/archives.html + [ok] writing $PATH/output/tag/tutoriel.html + [ok] writing $PATH/output/tag/git.html + [ok] writing $PATH/output/category/GNU-Linux.html + + +Première analyse +================ + +Nous allons décortiquer un peu tout ça ensemble. + +* Un dossier output/ a été créé pour y mettre le fichiers xml et html du blog. +* Dans le dossier feeds/, nous retrouvons les différents flux de syndication. +* Le fichier de l’article et la page principale du blog a été généré. +* Le répertoire tag/ propose une page par tag. +* La page correspondant à la catégorie est générée dans le répertoire category/ + +Si vous ouvrez le fichier index.html — ou un autre — avec votre navigateur, vous +remarquerez que : + +* Le thème utilisé par défaut est notmyidea +* Le nom du blog est A Pelican Blog. + +Bien évidemment, il y a des paramètres de base que l’on peut modifier pour mettre +un peu tout ça à sa sauce. C’est ce que nous allons voir au travers du fichier de configuration. + + diff --git a/docs/fr/configuration.rst b/docs/fr/configuration.rst new file mode 100644 index 00000000..5f61a3ba --- /dev/null +++ b/docs/fr/configuration.rst @@ -0,0 +1,154 @@ +Fichier de configuration +************************ + +On va créer un fichier de configuration que l’on va appeler **settings.py**. On peut +utiliser Pelican sans faire ce fichier, mais il faudrait à chaque fois passer les paramètres +en ligne de commande. Et comme il va nous servir à faire d’autres choses bien utile, +autant l’appréhender de suite. Cependant, nous n’allons voir que la base pour l’instant. + +Paramètres de base +================== + +AUTHOR : + Désigne l’auteur par défaut ; + +DEFAULT_CATEGORY : + La catégorie par défaut des articles. Si ce paramètre n’est + pas documenté, il prendra la valeur misc — pour miscellaneous (divers en français) ; + +SITENAME : + Le nom de votre site ; + +OUTPUT_PATH : + Le répertoire de sortie du blog. + +Quand je dis qu’on va faire simple, on fait simple ! +Passons donc à ce quoi doit ressembler le fichier de configuration :: + + # -*- coding: utf-8 -*- + AUTHOR = "Guillaume" + DEFAULT_CATEGORY = "GNU-Linux" + SITENAME = "Free Culture" + + +Si vous avez un serveur comme Apache de configuré pour votre machine, vous +pouvez paramétrer le répertoire de sortie vers **/var/www/blog** par exemple :: + + OUTPUT_PATH = "/var/www/blog" + +Une remarque importante. Si vous avez besoin de passer un caractère accentué, il +faut le préciser que la chaine est en unicode en faisant par exemple +*AUTHOR = u"Guillaume LAMÉ"* + +Pour bien vérifier que les paramètres sont bien pris en compte, nous allons enlever les lignes *:author: Guillaume* et *:category: GNU-Linux* de notre fichier +**premier_article.rst** et regénérer le blog. + +Rafraichissez votre page, ce devrait être bon. + +Nous allons maintenant passer en revue les différents paramètres de Pelican. Je les +ai regroupé par thème. Cependant, c’est surtout un listing avant de rentrer dans les +détails au prochain chapitre. + +Flux de syndication +=================== + +CATEGORY_FEED : + Chemin d’écriture des flux Atom liés aux catégories ; + +CATEGORY_FEED_RSS : + Idem pour les flux rss (Optionnel); + +FEED : + Chemin du flux Atom global ; + +FEED_RSS : + Chemin du flux Rss global (Optionnel); + +TAG_FEED : + Chemin des flux Atom pour les tags (Optionnel); + +TAG_FEED_RSS : + Chemin des flux Rss pour les tags (Optionnel). + + +Traductions +=========== + +DEFAULT_LANG : + Le langage par défaut à utiliser. «*en*» par défaut ; + +TRANSLATION_FEED : + Chemin du flux pour les traductions. + + +Thèmes +====== + +CSS_FILE : + Fichier css à utiliser si celui-ci est différent du fichier par défaut (*main.css*) ; + +DISPLAY_PAGES_ON_MENU : + Affiche ou non les pages statiques sur le menu du thème ; + +DISQUS_SITENAME : + Indiquer le nom du site spécifié sur Disqus ; + +GITHUB_URL : + Indiquez votre url Github ; + +GOOGLE_ANALYTICS : + 'UA-XXXX-YYYY' pour activer Google analytics ; + +JINJA_EXTENSIONS : + Liste d'extension Jinja2 que vous souhaitez utiliser ; + +LINKS : + Une liste de tuples (Titre, url) pour afficher la liste de lien ; + +PDF_PROCESSOR : + Génère ou non les articles et pages au format pdf ; + +REVERSE_ARCHIVE_ORDER : + Met les articles plus récent en tête de l'archive ; + +SOCIAL : + Une liste de tuples (Titre, url) pour afficher la liste de lien dans la section "Social" ; + +STATIC_THEME_PATHS : + Répertoire du thème que vous souhaitez importer dans l'arborescence finale ; + +THEME : + Thème à utiliser: + +TWITTER_USERNAME : + Permet d'afficher un bouton permettant le tweet des articles. + + + + + +Paramètres divers +================= + +FALLBACK_ON_FS_DATE : + Si *True*, Pelican se basera sur le *mtime* du fichier s'il n'y a pas de date spécifiée dans le fichier de l'article ; + +KEEP_OUTPUT DIRECTORY : + Ne génère que les fichiers modifiés et n'efface pas le repertoire de sortie ; + +MARKUP : + Langage de balisage à utiliser ; + +PATH : + Répertoire à suivre pour les fichiers inclus ; + +SITEURL : + URL de base de votre site ; + +STATIC_PATHS : + Les chemins statiques que vous voulez avoir accès sur le chemin de sortie "statique" ; + + + + + diff --git a/docs/fr/conventions.rst b/docs/fr/conventions.rst new file mode 100644 index 00000000..bf88c07e --- /dev/null +++ b/docs/fr/conventions.rst @@ -0,0 +1,18 @@ +Conventions +########### + +Environnement de test +===================== + +Les exemples sont basées sur une distribution Debian. Pour les autres distributions, +il y aura des ajustements à faire, notamment pour l’installation de Pelican. Les +noms des paquets peuvent changer. + +Conventions typographiques +========================== + +Un petit rappel concernant les codes sources. + + * $ correspond à une ligne à exécuter en tant qu’utilisateur courant du systême ; + * # correspond à une ligne à exécuter en tant que root ; + * **settings.py** : Les noms des répertoires et fichiers sont en gras. diff --git a/docs/fr/faq.rst b/docs/fr/faq.rst new file mode 100644 index 00000000..8cbe0881 --- /dev/null +++ b/docs/fr/faq.rst @@ -0,0 +1,35 @@ +*Foire aux questions (FAQ)* + +Voici un résumé des questions fréquemment posées pour pelican. + +*Est-il obligatoire d'avoir un fichier de configuration ?* + +Non. Les fichiers de configuration sont juste un moyen facile de configurer +pelican. Pour les opérations de base, il est possible de spécifier des +options +en invoquant pelican avec la ligne de commande (voir pelican --help pour +plus +d'informations à ce sujet) + +*Je crée mon propre thème, comment utiliser pygments?* + +Pygment ajoute quelques classes au contenu généré, de sorte qua colorisation +de votre thème se fait grâce à un fichier css. Vous pouvez jeter un oeil à +celui proposé par`sur le site du projet `_ + +*Comment puis-je créer mon propre thèm* + +Vueillez vous référer à :ref:`theming-pelican-fr`. + +*Comment puis-je aider?* + +Vous avez plusieurs options pour aider. Tout d'abord, vous pouvez utiliser +le +pélican, et signaler toute idée ou problème que vous avez sur le bugtracker +. + +Si vous voulez contribuer, jeter un oeil au dépôt git , ajoutez vos +modifications et faites une demande, je les regarderai dès que possible + +Vous pouvez aussi contribuer en créant des thèmes, et/ou compléter la +documentation. diff --git a/docs/fr/index.rst b/docs/fr/index.rst new file mode 100644 index 00000000..9d741af2 --- /dev/null +++ b/docs/fr/index.rst @@ -0,0 +1,55 @@ +Pelican +####### + +Pelican est un generateur de blog simple codé en python + +* Écrivez vos articles directement dans votre éditeur favori (vim !) et + directement en syntaxe reStructuredText ou Markdown ; +* Un outil simple en ligne de conmmande pour (re)générer le blog ; +* Sortie complètement statique, facile pour l'héberger n'importe où ; + +Fonctionnalités +=============== + +Pelican supporte actuellement : + +* des articles de blog ; +* des pages statiques ; +* les commentaires via un service externe (`disqus `_) + Notez qu'étant bien un service externe assez pratique, vous ne gérez pas + vous même les commentaires. Ce qui pourrait occasionner une perte de vos données; +* support de template (les templates sont crées avec `jinja2 `_) ; +* génération optionnelle de vos pages et articles en pdf. + +Pourquoi le nom "Pelican" ? +============================ + +Vous n'avez pas remarqué ? "Pelican" est un anagramme pour "Calepin" ;) + +Code source +=========== + +Vous pouvez accéder au code source via git à l'adresse +http://github.com/ametaireau/pelican/ + +Feedback ! +========== + +Si vous voulez de nouvelles fonctionnalitées pour Pelican, n'hésitez pas à nous le dire, +à cloner le dépôt, etc … C'est open source !!! + +Contactez Alexis à "alexis at notmyidea dot org" pour quelques requêtes ou retour d'expérience que ce soi ! + +Documentation +============= + +.. toctree:: + :maxdepth: 2 + + conventions + installation + bases + configuration + parametres_article + astuces + faq diff --git a/docs/fr/installation.rst b/docs/fr/installation.rst new file mode 100644 index 00000000..e853979d --- /dev/null +++ b/docs/fr/installation.rst @@ -0,0 +1,67 @@ +Installation et mise à jour de Pelican +###################################### + +Installation +============ + +Il y a deux façons d’installer Pelican sur son système. La première est via l’utilitaire +pip, l’autre façon est de télécharger Pelican via Github. Ici nous allons voir les deux +façons de procéder. + +Via pip +------- + +Pour installer Pelican via pip, vous aurez besoin du paquet python-pip. puis installez Pelican :: + + # apt-get install python-pip + # pip install pelican + + +Via Github +---------- + +Pour installer Pelican en reprenant le code via Github, nous aurons besoin du paquet +git-core pour récupérez les sources de Pelican. Puis nous procédons à l’installation :: + + # apt-get install git-core + $ git clone https://github.com/ametaireau/pelican.git + $ cd pelican + # python setup.py install + +Mises à jour +============ + +Via pip +------- + +Rien de bien compliqué pour mettre à jour via pip :: + + $ cd votreRepertoireSource + $ pip install --upgrade pelican + + +Via Github +---------- + +C'est un peu plus long avec Github par contre :: + + $ cd votreRepertoireSource + $ git pull origin master + $ cd pelican + # python setup.py install + +Vous aurez un message d’erreur si le module setuptools de python n’est pas installé. +La manipulation est la suivante :: + + # apt-get install python-setuptools + +Alors, quelle méthode choisir ? +=============================== + +Vous avez le choix entre deux méthodes, mais aussi entre deux concepts. La méthode +de Github est la version de développement, où les modifications arrivent assez +fréquemment sans être testées à fond. La version de pip est une version arrêtée avec un +numéro de version dans laquelle vous aurez moins de bug. N’oubliez cependant pas +que le projet est très jeune et manque donc de maturité. Si vous aimez avoir les toutes +dernières versions utilisez Github, sinon penchez vous sur pip. + diff --git a/docs/fr/parametres_article.rst b/docs/fr/parametres_article.rst new file mode 100644 index 00000000..a3d25b55 --- /dev/null +++ b/docs/fr/parametres_article.rst @@ -0,0 +1,106 @@ +Les paramètres des articles dans Pelican +######################################## + +Les catégories +============== + +Nous avons vu que pour affecter un article à une catégorie, nous avions le paramètre *:category:*. +Il y a cependant plus simple, affecter un répertoire à une catégorie. + +Dans le répertoire ou vous avez vos articles, créez le repertoire **GNU-Linux** et déplacez y le fichier +**premier_article.rst**. Bien évidemment nous ne verront pas la différence, car jusqu'ici *GNU-Linux* +est notre catégorie par défaut. + +Nous allons faire un autre exemple d'article avec la catégorie Pelican. Créez le répertoire **Pelican** +et collez cette exemple d'article :: + + Préparation de la documentation + ############################### + + :date: 2011-01-27 15:28 + :tags: documentation + + Il y a quand même pas mal de boulot pour faire une documentation ! + +Et lancez la compilation du blog. Vous voyez que la catégorie est affectée automatiquement. + +Les tags +======== + +Pour les tags, il n'y a rien de compliqué. il suffit de mettre le(s) tags séparés si besoin d'une virgule. :: + + Préparation de la documentation + ############################### + + :date: 2011-01-27 15:28 + :tags: documentation, pelican + +Par contre, par soucis de clarté au niveau des url je vous conseille de mettre les expression de plusieurs +mots séparées par des tirets :: + + :tags: mise-a-jour + +et non :: + + :tags: mise a jour + + +Les auteurs +=========== + +Par défaut, vous pouvez indiqué votre nom en tant qu'auteur dans le fichier de configuration. +S'il y a plusieurs auteurs pour le site, vous pouvez le définir manuellement dans +l'article avec la méta-donnée :: + + :author: Guillaume + +La date +======= + +La date se met au format anglophone : **YYYY-MM-DD hh:mm** :: + + :date: 2011-01-31 14:12 + + +Les traductions +=============== + +Pelican permet de générer un blog multilingue assez facilement. Pour cela nous devons : + +* Définir la langue de base du blog ; +* Donner une référence à l'article initial ; +* Définir la langue du fichier traduit et y reporter la référence. + +Pour définir la langue de base nous allons modifier le fichier **settings.py** et y rajouter la ligne suivante :: + + DEFAULT_LANG = "fr" + +Puis ajouter la référence dans notre article d'origine qui deviendra :: + + Préparation de la documentation + ############################### + + :date: 2011-01-27 15:28 + :tags: documentation + :slug: preparation-de-la-documentation + + Il y a quand même pas mal de boulot pour faire une documentation ! + +Nous n'avons plus qu'à créer l'article en anglais :: + + Start of documentation + ###################### + + :slug: preparation-de-la-documention + :lang: en + + There are still a lot of work to documentation ! + +**Il est important de comprendre que la valeur de :slug: deviendra votre url. Ne mettez donc pas un diminutif pour +identifier l'article** + +Rien de plus à savoir pour traduire efficacement des articles. + + +Maintenant que vous avez toutes les clés en main pour créer un article, nous allons passer à la personnalisation +du fichier de configuration. diff --git a/docs/getting_started.rst b/docs/getting_started.rst index f66a6f06..d90e1fe8 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -17,22 +17,26 @@ install. I recommend to do so in a virtualenv:: $ python setup.py install Dependencies -============ +------------ At this time, pelican is dependent of the following python packages: * feedgenerator, to generate the ATOM feeds. * jinja2, for templating support. -* pygments, to have syntactic colorization -* docutils and Markdown If you're not using python 2.7, you will also need `argparse`. -All those dependencies will be processed automatically if you install pelican -using setuptools/distribute or pip. +Optionally: + +* docutils, for reST support +* pygments, to have syntactic colorization with resT input +* Markdown, for Markdown as an input format + +Writing articles using pelican +============================== Files metadata -============== +-------------- Pelican tries to be smart enough to get the informations he needs from the file system (for instance, about the category of your articles), but you need to @@ -63,11 +67,11 @@ directory where the rst file is. For instance, the category of `python/foobar/myfoobar.rst` is `foobar`. Generate your blog -================== +------------------ To launch pelican, just use the `pelican` command:: - $ pelican /path/to/your/content/ + $ pelican /path/to/your/content/ [-s path/to/your/settings.py] And… that's all! You can see your weblog generated on the `content/` folder. @@ -80,7 +84,7 @@ the options you can use:: $ pelican --help Pages -===== +----- If you create a folder named `pages`, all the files in it will be used to generate static pages. @@ -89,9 +93,60 @@ Then, use the `DISPLAY_PAGES_ON_MENU` setting, which will add all the pages to the menu. Translations -============ +------------ -It is possible to translate articles. To do so, you need to add a `Lang` meta +It is possible to translate articles. To do so, you need to add a `lang` meta in your articles/pages, and to set a `DEFAULT_LANG` setting (which is en by -default). Then, only articles with this default language will be listed, and +default). +Then, only articles with this default language will be listed, and each article will have a translation list. + +Pelican uses the "slug" of two articles to compare if they are translations of +each others. So it's possible to define (in restructured text) the slug +directly. + +Here is an exemple of two articles (one in english and the other one in +french). + +The english one:: + + Foobar is not dead + ################## + + :slug: foobar-is-not-dead + :lang: en + + That's true, foobar is still alive ! + +And the french one:: + + Foobar n'est pas mort ! + ####################### + + :slug: foobar-is-not-dead + :lang: fr + + Oui oui, foobar est toujours vivant ! + +Despite the text quality, you can see that only the slug is the same here. +You're not forced to define the slug that way, and it's completely possible to +have two translations with the same title (which defines the slug) + +Syntactic recognition +--------------------- + +Pelican is able to regognise the syntax you are using, and to colorize the +right way your block codes. To do so, you have to use the following syntax:: + + .. code-block:: identifier + your code goes here + +The identifier is one of the lexers available `here +`_. + +Autoreload +---------- + +It's possible to tell pelican to watch for your modifications, instead of +manually launching it each time you need. Use the `-r` option, or +`--autoreload`. diff --git a/docs/index.rst b/docs/index.rst index 5fd8f8b7..a370a94f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -29,8 +29,7 @@ Heh, you didn't noticed? "Pelican" is an anagram for "Calepin" ;) Source code =========== -You can access the source code via mercurial at http://hg.notmyidea.org/pelican/ -or via git on http://github.com/ametaireau/pelican/ +You can access the source code via git on http://github.com/ametaireau/pelican/ Feedback ! ========== @@ -43,6 +42,8 @@ Contact me at "alexis at notmyidea dot org" for any request/feedback ! Documentation ============= +A french version of the documentation is available at :doc:`fr/index`. + .. toctree:: :maxdepth: 2 @@ -50,3 +51,4 @@ Documentation settings themes internals + faq diff --git a/docs/internals.rst b/docs/internals.rst index 80fc8661..4ff8c91c 100644 --- a/docs/internals.rst +++ b/docs/internals.rst @@ -40,7 +40,8 @@ method, that is returning an HTML content and some metadata. Take a look to the Markdown reader:: - class MarkdownReader(object): + class MarkdownReader(Reader): + enabled = bool(Markdown) def read(self, filename): """Parse content and metadata of markdown files""" @@ -59,6 +60,12 @@ Take a look to the Markdown reader:: Simple isn't it ? +If your new reader requires additional Python dependencies then you should wrap +their `imports` statements in `try...except`. Then inside the reader's class +set the `enabled` class attribute to mark import success or failure. This makes +it possible for users to continue using their favourite markup method without +needing to install modules for all the additional formats they don't use. + How to implement a new generator ? ================================== diff --git a/docs/settings.rst b/docs/settings.rst index 853b5745..67039832 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -19,67 +19,135 @@ processed. Here are the available settings. Please note that all the settings you put in this file will be passed to the templates as well. -======================= ======================================================= -Setting name what it does ? -======================= ======================================================= -`AUTHOR` Default author (put your name) -`CATEGORY_FEED` Where to put the atom categories feeds. default is - `feeds/%s.atom.xml`, where %s is the name of the - category. -`CATEGORY_FEED_RSS` Where to put the categories rss feeds. default is None - (no rss) -`CSS_FILE` To specify the CSS file you want to load, if it's not - the default one ('main.css') -`DEFAULT_CATEGORY` The default category to fallback on. `misc` by default. -`DEFAULT_LANG` The default language to use. Default is 'en'. -`DISPLAY_PAGES_ON_MENU` Display or not the pages on the menu of the template. - Templates can follow or not this settings. -`DIRECT_TEMPLATES` Tuple, containing templates to render. There should be - a html file for each of these templates in the theme. -`FALLBACK_ON_FS_DATE` If True, pelican will use the file system dates infos - (mtime) if it can't get informations from the - metadata? -`FEED` relative url to output the atom feed. Default is - `feeds/all.atom.xml` -`FEED_RSS` relative url to output the rss feed. Default is - None (no rss) -`KEEP_OUTPUT_DIRECTORY` Keep the output directory and just update all the generated files. - Default is to delete the output directory. -`MARKUP` A list of available markup languages you want to use. - For the moment, only available values are `rst` and `md`. -`OUTPUT_PATH` Where to output the generated files. Default to - "output" -`PATH` path to look at for input files. -`PDF_PROCESSOR` Put True if you want to have PDF versions of your - documents. You will need to install `rst2pdf`. -`REVERSE_ARCHIVE_ORDER` Reverse the archives order. (True makes it in - descending order: the newer first) -`SITEURL` base URL of your website. -`SITENAME` Your site name, -`STATIC_PATHS` The static paths you want to have accessible on the - output path "static". By default, pelican will copy - the 'images' folder to the output folder. -`STATIC_THEME_PATHS` Static theme paths you want to copy. Default values - is `static`, but if your theme have others static paths, - you can put them here. -`TAG_CLOUD_STEPS` Count of different font sizes in the tag cloud. -`TAG_CLOUD_MAX_ITEMS` Maximum tags count in the cloud. -`THEME` theme to use to product the output. can be the - complete static path to a theme folder, or chosen - between the list of default themes (see below) -`TRANSLATION_FEED` Where to put the RSS feed for translations. Default - is feeds/all-%s.atom.xml where %s is the name of the - lang. -======================= ======================================================= + +======================== ======================================================= +Setting name what it does ? +======================== ======================================================= +`AUTHOR` Default author (put your name) +`CATEGORY_FEED` Where to put the atom categories feeds. default is + `feeds/%s.atom.xml`, where %s is the name of the + category. +`CATEGORY_FEED_RSS` Where to put the categories rss feeds. default is None + (no rss) +`CSS_FILE` To specify the CSS file you want to load, if it's not + the default one ('main.css') +`DATE_FORMATS` If you do manage multiple languages, you can set + the date formatting here. +`DEFAULT_CATEGORY` The default category to fallback on. `misc` by default. +`DEFAULT_DATE_FORMAT` The default date format you want to use. +`DEFAULT_LANG` The default language to use. Default is 'en'. +`DEFAULT_ORPHANS` The minimum number of articles allowed on the last + page, defaults to zero. Use this when you don't want + to have a last page with very few articles. +`DEFAULT_PAGINATION` The maximum number of articles to include on a page, + not including orphans. Default is 5. +`DISPLAY_PAGES_ON_MENU` Display or not the pages on the menu of the template. + Templates can follow or not this settings. +`FALLBACK_ON_FS_DATE` If True, pelican will use the file system dates infos + (mtime) if it can't get informations from the + metadata? +`FEED` relative url to output the atom feed. Default is + `feeds/all.atom.xml` +`FEED_RSS` relative url to output the rss feed. Default is + None (no rss) +`JINJA_EXTENSIONS` A list of any Jinja2 extensions you want to use. + Default is no extensions (the empty list). +`KEEP_OUTPUT_DIRECTORY` Keep the output directory and just update all the + generated files. +`LOCALE` Change the locale. Default is the system locale. + Default is to delete the output directory. +`MARKUP` A list of available markup languages you want to use. + For the moment, only available values are `rst` and `md`. +`OUTPUT_PATH` Where to output the generated files. Default to + "output" +`PATH` path to look at for input files. +`PDF_PROCESSOR` Put True if you want to have PDF versions of your + documents. You will need to install `rst2pdf`. +`REVERSE_ARCHIVE_ORDER` Reverse the archives order. (True makes it in + descending order: the newer first) +`REVERSE_CATEGORY_ORDER` Reverse the category order. (True makes it in + descending order, default is alphabetically) +`SITEURL` base URL of your website. +`SITENAME` Your site name, +`SKRIBIT_TYPE` The type of skribit widget (TAB or WIDGET). +`SKRIBIT_TAB_COLOR` Tab color (#XXXXXX, default #333333). +`SKRIBIT_TAB_HORIZ` Tab Distance from Left (% or distance, default Null). +`SKRIBIT_TAB_VERT` Tab Distance from Top (% or distance, default 20%). +`SKRIBIT_TAB_PLACEMENT` Tab placement (Top, Bottom, Left or Right, default + LEFT). +`SKRIBIT_TAB_SITENAME` Tab identifier (See Skribit part below). +`SKRIBIT_WIDGET_ID` Widget identifier (See Skribit part below). +`STATIC_PATHS` The static paths you want to have accessible on the + output path "static". By default, pelican will copy + the 'images' folder to the output folder. +`STATIC_THEME_PATHS` Static theme paths you want to copy. Default values + is `static`, but if your theme have others static paths, + you can put them here. +`TAG_CLOUD_STEPS` Count of different font sizes in the tag cloud. +`TAG_CLOUD_MAX_ITEMS` Maximum tags count in the cloud. +`THEME` theme to use to product the output. can be the + complete static path to a theme folder, or chosen + between the list of default themes (see below) +`TRANSLATION_FEED` Where to put the RSS feed for translations. Default + is feeds/all-%s.atom.xml where %s is the name of the + lang. +`WITH_PAGINATION` Activate pagination. Default is False. +======================== ======================================================= + +Skribit +======= + +Skribit has two ways to display suggestions : as a sidebar widget or as a +suggestions tab. You can choose one of the display by setting the SKRIBIT_TYPE +in your config. + +Sidebar widget +-------------- + +The settings for sidebar widget is : + + * SKRIBIT_WIDGET_ID : the identifier of your blog. + +All the customizations are done in the skribit web interface. + +To retrieve your identifier from the code snippet, you can use this python code:: + + import re + regex = re.compile('.*http://assets.skribit.com/javascripts/SkribitWidget.\ + js\?renderTo=writeSkribitHere&blog=(.*)&.*') + snippet = '''SNIPPET CONTENT''' + snippet = snippet.replace('\n', '') + identifier = regex.match(snippet).groups()[0] + +Suggestion tab +-------------- + +The setting for suggestion tab's customizations are : + + * SKRIBIT_TAB_COLOR + * SKRIBIT_TAB_DISTANCE_HORIZ + * SKRIBIT_TAB_DISTANCE_VERT + * SKRIBIT_TAB_PLACEMENT + +The identifier is : + + * SKRIBIT_TAB_SITENAME : the identifier of your blog + +To retrieve your sitename from the code snippet, you can use this python code:: + + import re + regex = re.compile('.*http://skribit.com/lightbox/(.*)\',.*') + snippet = '''SNIPPET CONTENT''' + snippet = snippet.replace('\n', '') + identifier = regex.match(snippet).groups()[0] Themes ====== -3 themes are available. You can specify them using the `-t` option: +By default, two themes are availablee. You can specify them using the `-t` option: * notmyidea * simple (a synonym for "full text" :) -* martyalchin You can define your own theme too, and specify it's emplacement in the same way (be sure to specify the full absolute path to it). @@ -87,6 +155,8 @@ way (be sure to specify the full absolute path to it). Here is `a guide on how to create your theme `_ +You can find a list of themes at http://github.com/ametaireau/pelican-themes. + The `notmyidea` theme can make good use of the following settings. I recommend to use them too in your themes. @@ -102,6 +172,9 @@ Setting name what it does ? the header. `SOCIAL` A list of tuples (Title, Url) to appear in the "social" section. +`TWITTER_USERNAME` Allows to add a button on the articles to tweet about + them. Add you twitter username if you want this + button to appear. ======================= ======================================================= In addition, you can use the "wide" version of the `notmyidea` theme, by diff --git a/docs/themes.rst b/docs/themes.rst index 633acaaf..9f8b8765 100644 --- a/docs/themes.rst +++ b/docs/themes.rst @@ -1,8 +1,13 @@ +.. _theming-pelican: + How to create themes for pelican ################################ Pelican uses the great `jinja2 `_ templating engine to -generate it's HTML output. +generate it's HTML output. The jinja2 syntax is really simple. If you want to +create your own theme, feel free to take inspiration from the "simple" theme, +which is available `here +`_ Structure ========= @@ -61,18 +66,50 @@ categories A dict containing each category (keys), and the pages The list of pages ============= =================================================== +index.html +---------- + +Home page of your blog, will finally remain at output/index.html. + +If pagination is active, next pages will remain at output/index`n`.html. + +=================== =================================================== +Variable Description +=================== =================================================== +articles_paginator A paginator object of article list +articles_page The current page of articles +dates_paginator A paginator object of article list, ordered by date, + ascending +dates_page The current page of articles, ordered by date, + ascending +page_name 'index'. Useful for pagination links. +=================== =================================================== + category.html ------------- This template will be processed for each of the existing categories, and will finally remain at output/category/`category_name`.html. -============= =================================================== -Variable Description -============= =================================================== -articles The articles of this category -category The name of the category being processed -============= =================================================== +If pagination is active, next pages will remain at +output/category/`category_name``n`.html. + +=================== =================================================== +Variable Description +=================== =================================================== +category The name of the category being processed +articles Articles of this category +dates Articles of this category, but ordered by date, + ascending +articles_paginator A paginator object of article list +articles_page The current page of articles +dates_paginator A paginator object of article list, ordered by date, + ascending +dates_page The current page of articles, ordered by date, + ascending +page_name 'category/`category_name`'. Useful for pagination + links. +=================== =================================================== article.html ------------- @@ -91,11 +128,38 @@ tag.html -------- For each tag, this template will be processed. It will create .html files in -/output/tag/`tag_name`.html +/output/tag/`tag_name`.html. -============= =================================================== -Variable Description -============= =================================================== -tag The name of the tag being processed -articles Articles related to this tag -============= =================================================== +If pagination is active, next pages will remain at +output/tag/`tag_name``n`.html. + +=================== =================================================== +Variable Description +=================== =================================================== +tag The name of the tag being processed +articles Articles related to this tag +dates Articles related to this tag, but ordered by date, + ascending +articles_paginator A paginator object of article list +articles_page The current page of articles +dates_paginator A paginator object of article list, ordered by date, + ascending +dates_page The current page of articles, ordered by date, + ascending +page_name 'tag/`tag_name`'. Useful for pagination links. +=================== =================================================== + +Include skribit script +====================== + +In order to support skribit scripts in your themes, you must following these +actions : + + * Copy `skribit_tab_script.html` and `skribit_widget_script.html` in your + templates directory. + * Add {% include 'skribit_tab_script.html' %} in your part in order to + support suggestions tab. + * Add {% include 'skribit_widget_script.html' %} where you want in order to + support sidebar widget. + +You can take a look at notmyidea default theme for working example. diff --git a/pelican/__init__.py b/pelican/__init__.py index 915d92c7..e1636149 100755 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -1,87 +1,92 @@ import argparse import os +from functools import partial -from pelican.settings import read_settings -from pelican.utils import clean_output_dir -from pelican.writers import Writer from pelican.generators import (ArticlesGenerator, PagesGenerator, - StaticGenerator, PdfGenerator) + StaticGenerator, PdfGenerator) +from pelican.settings import read_settings +from pelican.utils import clean_output_dir, files_changed +from pelican.writers import Writer -VERSION = "2.5.3" +VERSION = "2.6.0" -def init_params(settings=None, path=None, theme=None, output_path=None, - markup=None, keep=False): - """Read the settings, and performs some checks on the environment - before doing anything else. - """ - if settings is None: - settings = {} - settings = read_settings(settings) - path = path or settings['PATH'] - if path.endswith('/'): - path = path[:-1] +class Pelican(object): + def __init__(self, settings=None, path=None, theme=None, output_path=None, + markup=None, keep=False): + """Read the settings, and performs some checks on the environment + before doing anything else. + """ + self.path = path or settings['PATH'] + if not self.path: + raise Exception('you need to specify a path to search the docs on !') + if self.path.endswith('/'): + self.path = path[:-1] - # define the default settings - theme = theme or settings['THEME'] - output_path = output_path or settings['OUTPUT_PATH'] - output_path = os.path.realpath(output_path) - markup = markup or settings['MARKUP'] - keep = keep or settings['KEEP_OUTPUT_DIRECTORY'] + # define the default settings + self.settings = settings + self.theme = theme or settings['THEME'] + output_path = output_path or settings['OUTPUT_PATH'] + self.output_path = os.path.realpath(output_path) + self.markup = markup or settings['MARKUP'] + self.keep = keep or settings['KEEP_OUTPUT_DIRECTORY'] - # find the theme in pelican.theme if the given one does not exists - if not os.path.exists(theme): - theme_path = os.sep.join([os.path.dirname( - os.path.abspath(__file__)), "themes/%s" % theme]) - if os.path.exists(theme_path): - theme = theme_path - else: - raise Exception("Impossible to find the theme %s" % theme) + # find the theme in pelican.theme if the given one does not exists + if not os.path.exists(self.theme): + theme_path = os.sep.join([os.path.dirname( + os.path.abspath(__file__)), "themes/%s" % self.theme]) + if os.path.exists(theme_path): + self.theme = theme_path + else: + raise Exception("Impossible to find the theme %s" % theme) - # get the list of files to parse - if not path: - raise Exception('you need to specify a path to search the docs on !') + def run(self): + """Run the generators and return""" - return settings, path, theme, output_path, markup, keep + context = self.settings.copy() + generators = [ + cls( + context, + self.settings, + self.path, + self.theme, + self.output_path, + self.markup, + self.keep + ) for cls in self.get_generator_classes() + ] + + for p in generators: + if hasattr(p, 'generate_context'): + p.generate_context() + + # erase the directory if it is not the source + if os.path.realpath(self.path).startswith(self.output_path) and not self.keep: + clean_output_dir(self.output_path) + + writer = self.get_writer() + + for p in generators: + if hasattr(p, 'generate_output'): + p.generate_output(writer) -def run_generators(generators, settings, path, theme, output_path, markup, keep): - """Run the generators and return""" + def get_generator_classes(self): + generators = [ArticlesGenerator, PagesGenerator, StaticGenerator] + if self.settings['PDF_GENERATOR']: + generators.append(PdfGenerator) + return generators - context = settings.copy() - generators = [p(context, settings, path, theme, output_path, markup, keep) - for p in generators] + def get_writer(self): + return Writer(self.output_path, settings=self.settings) - for p in generators: - if hasattr(p, 'generate_context'): - p.generate_context() - - # erase the directory if it is not the source - if output_path not in os.path.realpath(path) and not keep: - clean_output_dir(output_path) - - writer = Writer(output_path) - - for p in generators: - if hasattr(p, 'generate_output'): - p.generate_output(writer) - - -def run_pelican(settings, path, theme, output_path, markup, delete): - """Run pelican with the given parameters""" - - params = init_params(settings, path, theme, output_path, markup, delete) - generators = [ArticlesGenerator, PagesGenerator, StaticGenerator] - if params[0]['PDF_GENERATOR']: # param[0] is settings - generators.append(PdfGenerator) - run_generators(generators, *params) def main(): parser = argparse.ArgumentParser(description="""A tool to generate a static blog, with restructured text input files.""") - parser.add_argument(dest='path', + parser.add_argument(dest='path', nargs='?', help='Path where to find the content files') parser.add_argument('-t', '--theme-path', dest='theme', help='Path where to find the theme templates. If not specified, it will' @@ -99,14 +104,37 @@ def main(): help='Keep the output directory and just update all the generated files.' 'Default is to delete the output directory.') parser.add_argument('--version', action='version', version=VERSION, - help="Print the pelican version and exit") + help='Print the pelican version and exit') + parser.add_argument('-r', '--autoreload', dest='autoreload', action='store_true', + help="Relaunch pelican each time a modification occurs on the content" + "files") args = parser.parse_args() # Split the markup languages only if some have been given. Otherwise, populate # the variable with None. markup = [a.strip().lower() for a in args.markup.split(',')] if args.markup else None - run_pelican(args.settings, args.path, args.theme, args.output, markup, args.keep) + if args.settings is None: + settings = {} + settings = read_settings(args.settings) + + cls = settings.get('PELICAN_CLASS') + if isinstance(cls, basestring): + module, cls_name = cls.rsplit('.', 1) + module = __import__(module) + cls = getattr(module, cls_name) + + pelican = cls(settings, args.path, args.theme, args.output, markup, args.keep) + + if args.autoreload: + while True: + try: + if files_changed(pelican.path, pelican.markup): + pelican.run() + except KeyboardInterrupt: + break + else: + pelican.run() if __name__ == '__main__': diff --git a/pelican/contents.py b/pelican/contents.py index bb6949fb..7097e946 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from pelican.utils import slugify, truncate_html_words @@ -11,12 +12,12 @@ class Page(object): mandatory_properties = ('title',) def __init__(self, content, metadatas={}, settings={}, filename=None): - self.content = content + self._content = content self.translations = [] self.status = "published" # default value for key, value in metadatas.items(): - setattr(self, key, value) + setattr(self, key.lower(), value) if not hasattr(self, 'author'): if 'AUTHOR' in settings: @@ -47,6 +48,21 @@ class Page(object): if filename: self.filename = filename + if not hasattr(self, 'date_format'): + if self.lang in settings['DATE_FORMATS']: + self.date_format = settings['DATE_FORMATS'][self.lang] + else: + self.date_format = settings['DEFAULT_DATE_FORMAT'] + + if hasattr(self, 'date'): + self.locale_date = self.date.strftime(self.date_format.encode('ascii','xmlcharrefreplace')).decode('utf') + + if not hasattr(self, 'summary'): + self.summary = property(lambda self: truncate_html_words(self.content, 50)).__get__(self, Page) + + # store the settings ref. + self._settings = settings + def check_properties(self): """test that each mandatory property is set.""" for prop in self.mandatory_properties: @@ -54,8 +70,12 @@ class Page(object): raise NameError(prop) @property - def summary(self): - return truncate_html_words(self.content, 50) + def content(self): + if hasattr(self, "_get_content"): + content = self._get_content() + else: + content = self._content + return content class Article(Page): diff --git a/pelican/generators.py b/pelican/generators.py index 6c67f07f..cb64145a 100755 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from operator import attrgetter, itemgetter from itertools import chain from functools import partial @@ -10,13 +11,10 @@ import random from jinja2 import Environment, FileSystemLoader from jinja2.exceptions import TemplateNotFound -from pelican.utils import update_dict, copytree, process_translations, open +from pelican.utils import copytree, get_relative_path, process_translations, open from pelican.contents import Article, Page, is_valid_content from pelican.readers import read_file -_TEMPLATES = ('index', 'tag', 'tags', 'article', 'category', 'categories', - 'archives', 'page') - class Generator(object): """Baseclass generator""" @@ -32,7 +30,10 @@ class Generator(object): # templates cache self._templates = {} self._templates_path = os.path.expanduser(os.path.join(self.theme, 'templates')) - self._env = Environment(loader = FileSystemLoader(self._templates_path)) + self._env = Environment( + loader=FileSystemLoader(self._templates_path), + extensions=self.settings.get('JINJA_EXTENSIONS', []), + ) def get_template(self, name): """Return the template by name. @@ -84,8 +85,8 @@ class ArticlesGenerator(Generator): self.articles = [] # only articles in default language self.translations = [] self.dates = {} - self.tags = {} - self.categories = {} + self.tags = defaultdict(list) + self.categories = defaultdict(list) super(ArticlesGenerator, self).__init__(*args, **kwargs) def generate_feeds(self, writer): @@ -97,7 +98,7 @@ class ArticlesGenerator(Generator): writer.write_feed(self.articles, self.context, self.settings['FEED_RSS'], feed_type='rss') - for cat, arts in self.categories.items(): + for cat, arts in self.categories: arts.sort(key=attrgetter('date'), reverse=True) writer.write_feed(arts, self.context, self.settings['CATEGORY_FEED'] % cat) @@ -135,26 +136,41 @@ class ArticlesGenerator(Generator): writer.write_file, relative_urls = self.settings.get('RELATIVE_URLS') ) - for template in self.settings.get('DIRECT_TEMPLATES'): - write('%s.html' % template, self.get_template(template), self.context, - blog=True) - - tag_template = self.get_template('tag') - for tag, articles in self.tags.items(): - write('tag/%s.html' % tag, tag_template, self.context, tag=tag, - articles=articles) - - category_template = self.get_template('category') - for cat in self.categories: - write('category/%s.html' % cat, category_template, self.context, - category=cat, articles=self.categories[cat]) + # to minimize the number of relative path stuff modification + # in writer, articles pass first article_template = self.get_template('article') for article in chain(self.translations, self.articles): write(article.save_as, article_template, self.context, article=article, category=article.category) + PAGINATED_TEMPLATES = self.settings.get('PAGINATED_DIRECT_TEMPLATES') + for template in self.settings.get('DIRECT_TEMPLATES'): + paginated = {} + if template in PAGINATED_TEMPLATES: + paginated = {'articles': self.articles, 'dates': self.dates} + write('%s.html' % template, self.get_template(template), self.context, + blog=True, paginated=paginated, page_name=template) + + # and subfolders after that + tag_template = self.get_template('tag') + for tag, articles in self.tags.items(): + dates = [article for article in self.dates if article in articles] + write('tag/%s.html' % tag, tag_template, self.context, tag=tag, + articles=articles, dates=dates, + paginated={'articles': articles, 'dates': dates}, + page_name='tag/%s' % tag) + + category_template = self.get_template('category') + for cat, articles in self.categories: + dates = [article for article in self.dates if article in articles] + write('category/%s.html' % cat, category_template, self.context, + category=cat, articles=articles, dates=dates, + paginated={'articles': articles, 'dates': dates}, + page_name='category/%s' % cat) + + def generate_context(self): """change the context""" @@ -166,8 +182,7 @@ class ArticlesGenerator(Generator): # if no category is set, use the name of the path as a category if 'category' not in metadatas.keys(): - category = os.path.dirname(f).replace( - os.path.expanduser(self.path)+'/', '') + category = os.path.basename(os.path.dirname(f)) if category == self.path: category = self.settings['DEFAULT_CATEGORY'] @@ -186,14 +201,14 @@ class ArticlesGenerator(Generator): if hasattr(article, 'tags'): for tag in article.tags: - update_dict(self.tags, tag, article) + self.tags[tag].append(article) all_articles.append(article) self.articles, self.translations = process_translations(all_articles) for article in self.articles: # only main articles are listed in categories, not translations - update_dict(self.categories, article.category, article) + self.categories[article.category].append(article) # sort the articles by date @@ -228,8 +243,13 @@ class ArticlesGenerator(Generator): random.shuffle(self.tag_cloud) # and generate the output :) + + # order the categories per name + self.categories = list(self.categories.items()) + self.categories.sort(reverse=self.settings.get('REVERSE_CATEGORY_ORDER')) self._update_context(('articles', 'dates', 'tags', 'categories', 'tag_cloud')) + def generate_output(self, writer): self.generate_feeds(writer) self.generate_pages(writer) @@ -304,7 +324,8 @@ class PdfGenerator(Generator): pass def generate_output(self, writer=None): - # we don't use the writer passed as argument here, since we write our own files + # we don't use the writer passed as argument here + # since we write our own files print u' Generating PDF files...' pdf_path = os.path.join(self.output_path, 'pdf') try: diff --git a/pelican/paginator.py b/pelican/paginator.py new file mode 100644 index 00000000..a2a452b9 --- /dev/null +++ b/pelican/paginator.py @@ -0,0 +1,85 @@ +# From django.core.paginator +from math import ceil + +class Paginator(object): + def __init__(self, object_list, per_page, orphans=0): + self.object_list = object_list + self.per_page = per_page + self.orphans = orphans + self._num_pages = self._count = None + + def page(self, number): + "Returns a Page object for the given 1-based page number." + bottom = (number - 1) * self.per_page + top = bottom + self.per_page + if top + self.orphans >= self.count: + top = self.count + return Page(self.object_list[bottom:top], number, self) + + def _get_count(self): + "Returns the total number of objects, across all pages." + if self._count is None: + self._count = len(self.object_list) + return self._count + count = property(_get_count) + + def _get_num_pages(self): + "Returns the total number of pages." + if self._num_pages is None: + hits = max(1, self.count - self.orphans) + self._num_pages = int(ceil(hits / float(self.per_page))) + return self._num_pages + num_pages = property(_get_num_pages) + + def _get_page_range(self): + """ + Returns a 1-based range of pages for iterating through within + a template for loop. + """ + return range(1, self.num_pages + 1) + page_range = property(_get_page_range) + +class Page(object): + def __init__(self, object_list, number, paginator): + self.object_list = object_list + self.number = number + self.paginator = paginator + + def __repr__(self): + return '' % (self.number, self.paginator.num_pages) + + def has_next(self): + return self.number < self.paginator.num_pages + + def has_previous(self): + return self.number > 1 + + def has_other_pages(self): + return self.has_previous() or self.has_next() + + def next_page_number(self): + return self.number + 1 + + def previous_page_number(self): + return self.number - 1 + + def start_index(self): + """ + Returns the 1-based index of the first object on this page, + relative to total objects in the paginator. + """ + # Special case, return zero if no items. + if self.paginator.count == 0: + return 0 + return (self.paginator.per_page * (self.number - 1)) + 1 + + def end_index(self): + """ + Returns the 1-based index of the last object on this page, + relative to total objects found (hits). + """ + # Special case for the last page because there can be orphans. + if self.number == self.paginator.num_pages: + return self.paginator.count + return self.number * self.paginator.per_page + diff --git a/pelican/readers.py b/pelican/readers.py index 1fc51f68..4e1d7b2e 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -1,11 +1,18 @@ -from docutils import core -from markdown import Markdown +# -*- coding: utf-8 -*- +try: + from docutils import core + + # import the directives to have pygments support + import rstdirectives +except ImportError: + core = False +try: + from markdown import Markdown +except ImportError: + Markdown = False import re import string -# import the directives to have pygments support -import rstdirectives - from pelican.utils import get_date, open @@ -16,7 +23,12 @@ _METADATAS_PROCESSORS = { } -class RstReader(object): +class Reader(object): + enabled = True + +class RstReader(Reader): + enabled = bool(core) + extension = "rst" def _parse_metadata(self, content): """Return the dict containing metadatas""" @@ -42,7 +54,9 @@ class RstReader(object): metadatas['title'] = title return content, metadatas -class MarkdownReader(object): +class MarkdownReader(Reader): + enabled = bool(Markdown) + extension = "md" def read(self, filename): """Parse content and metadata of markdown files""" @@ -58,8 +72,25 @@ class MarkdownReader(object): )(value[0]) return content, metadatas -_EXTENSIONS = {'rst': RstReader, 'md': MarkdownReader} # supported formats +class HtmlReader(Reader): + extension = "html" + _re = re.compile('\<\!\-\-\#\s?[A-z0-9_-]*\s?\:s?[A-z0-9\s_-]*\s?\-\-\>') + + def read(self, filename): + """Parse content and metadata of (x)HTML files""" + content = open(filename) + metadatas = {'title':'unnamed'} + for i in self._re.findall(content): + key = i.split(':')[0][5:].strip() + value = i.split(':')[-1][:-3].strip() + metadatas[key.lower()] = value + + return content, metadatas + + + +_EXTENSIONS = dict((cls.extension, cls) for cls in Reader.__subclasses__()) def read_file(filename, fmt=None): """Return a reader object using the given format.""" @@ -68,4 +99,6 @@ def read_file(filename, fmt=None): if fmt not in _EXTENSIONS.keys(): raise TypeError('Pelican does not know how to parse %s' % filename) reader = _EXTENSIONS[fmt]() + if not reader.enabled: + raise ValueError("Missing dependencies for %s" % fmt) return reader.read(filename) diff --git a/pelican/settings.py b/pelican/settings.py index 85f7a6a5..6c0918a0 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -1,4 +1,6 @@ +# -*- coding: utf-8 -*- import os +import locale _DEFAULT_THEME = os.sep.join([os.path.dirname(os.path.abspath(__file__)), "themes/notmyidea"]) @@ -18,6 +20,7 @@ _DEFAULT_CONFIG = {'PATH': None, 'FALLBACK_ON_FS_DATE': True, 'CSS_FILE': 'main.css', 'REVERSE_ARCHIVE_ORDER': False, + 'REVERSE_CATEGORY_ORDER': False, 'KEEP_OUTPUT_DIRECTORY': False, 'CLEAN_URLS': False, # use /blah/ instead /blah.html in urls 'RELATIVE_URLS': True, @@ -25,6 +28,15 @@ _DEFAULT_CONFIG = {'PATH': None, 'TAG_CLOUD_STEPS': 4, 'TAG_CLOUD_MAX_ITEMS': 100, 'DIRECT_TEMPLATES': ('index', 'tags', 'categories', 'archives'), + 'PAGINATED_DIRECT_TEMPLATES': ('index', ), + 'PELICAN_CLASS': 'pelican.Pelican', + 'DEFAULT_DATE_FORMAT': '%a %d %B %Y', + 'DATE_FORMATS': {}, + 'JINJA_EXTENSIONS': [], + 'LOCALE': '', # default to user locale + 'WITH_PAGINATION': False, + 'DEFAULT_PAGINATION': 5, + 'DEFAULT_ORPHANS': 0, } def read_settings(filename): @@ -37,4 +49,7 @@ def read_settings(filename): for key in tempdict: if key.isupper(): context[key] = tempdict[key] + + # set the locale + locale.setlocale(locale.LC_ALL, context['LOCALE']) return context diff --git a/pelican/themes/brownstone/static/css/pygment.css b/pelican/themes/brownstone/static/css/pygment.css deleted file mode 100644 index 594b0fa3..00000000 --- a/pelican/themes/brownstone/static/css/pygment.css +++ /dev/null @@ -1,205 +0,0 @@ -.hll { -background-color:#FFFFCC; -} -.c { -color:#408090; -font-style:italic; -} -.err { -border:1px solid #FF0000; -} -.k { -color:#007020; -font-weight:bold; -} -.o { -color:#666666; -} -.cm { -color:#408090; -font-style:italic; -} -.cp { -color:#007020; -} -.c1 { -color:#408090; -font-style:italic; -} -.cs { -background-color:#FFF0F0; -color:#408090; -} -.gd { -color:#A00000; -} -.ge { -font-style:italic; -} -.gr { -color:#FF0000; -} -.gh { -color:#000080; -font-weight:bold; -} -.gi { -color:#00A000; -} -.go { -color:#303030; -} -.gp { -color:#C65D09; -font-weight:bold; -} -.gs { -font-weight:bold; -} -.gu { -color:#800080; -font-weight:bold; -} -.gt { -color:#0040D0; -} -.kc { -color:#007020; -font-weight:bold; -} -.kd { -color:#007020; -font-weight:bold; -} -.kn { -color:#007020; -font-weight:bold; -} -.kp { -color:#007020; -} -.kr { -color:#007020; -font-weight:bold; -} -.kt { -color:#902000; -} -.m { -color:#208050; -} -.s { -color:#4070A0; -} -.na { -color:#4070A0; -} -.nb { -color:#007020; -} -.nc { -color:#0E84B5; -font-weight:bold; -} -.no { -color:#60ADD5; -} -.nd { -color:#555555; -font-weight:bold; -} -.ni { -color:#D55537; -font-weight:bold; -} -.ne { -color:#007020; -} -.nf { -color:#06287E; -} -.nl { -color:#002070; -font-weight:bold; -} -.nn { -color:#0E84B5; -font-weight:bold; -} -.nt { -color:#062873; -font-weight:bold; -} -.nv { -color:#BB60D5; -} -.ow { -color:#007020; -font-weight:bold; -} -.w { -color:#BBBBBB; -} -.mf { -color:#208050; -} -.mh { -color:#208050; -} -.mi { -color:#208050; -} -.mo { -color:#208050; -} -.sb { -color:#4070A0; -} -.sc { -color:#4070A0; -} -.sd { -color:#4070A0; -font-style:italic; -} -.s2 { -color:#4070A0; -} -.se { -color:#4070A0; -font-weight:bold; -} -.sh { -color:#4070A0; -} -.si { -color:#70A0D0; -font-style:italic; -} -.sx { -color:#C65D09; -} -.sr { -color:#235388; -} -.s1 { -color:#4070A0; -} -.ss { -color:#517918; -} -.bp { -color:#007020; -} -.vc { -color:#BB60D5; -} -.vg { -color:#BB60D5; -} -.vi { -color:#BB60D5; -} -.il { -color:#208050; -} diff --git a/pelican/themes/brownstone/static/css/style.css b/pelican/themes/brownstone/static/css/style.css deleted file mode 100644 index fa8fe165..00000000 --- a/pelican/themes/brownstone/static/css/style.css +++ /dev/null @@ -1,414 +0,0 @@ - -/* -Design by Free CSS Templates -http://www.freecsstemplates.org -Released for free under a Creative Commons Attribution 2.5 License -*/ -@import url("pygment.css"); -body { - margin: 30px 0px 0px 0px; - padding: 0; - background: #7E776F url('../images/img01.jpg') repeat left top; - font-family: Arial, Helvetica, sans-serif; - font-size: 13px; - color: #3E3B36; -} -.summary h2{font-size:1.6em; color:black;} -h1, h2, h3 { - margin: 0; - padding: 0; - font-weight: normal; - color: #F0E9E9; -} - -h1 { - font-size: 2em; -} - -h2 { - font-size: 2.8em; -} - -h3 { - font-size: 1.6em; -} - -p, ul, ol { - margin-top: 0; - line-height: 180%; -} - -ul, ol { -} - -a { - text-decoration: none; - color: #4D8D99; -} - -a:hover { -} - -#wrapper { - margin: 0 auto; - padding: 0; -} - -/* Header */ - -#header-wrapper { - height: 100px; - background: #3C3230; - border-bottom: 10px solid #4F4440; -} - -#header { - width: 950px; - margin: 0 auto; - padding: 0px 0px 0px 30px; -} - -/* Logo */ - -#logo { - width: 280px; - height: 140px; - margin: 0; - padding: 0; - background: url('../images/img07.jpg') no-repeat left top; - color: #34312C; -} - -#logo h1, #logo p { - margin: 0; - padding: 0; - letter-spacing: -2px; - text-align: center; - font-family: Georgia, "Times New Roman", Times, serif; -} - -#logo h1 { - margin: 0px 0px -20px 0px; - padding: 20px 0px 0px 0px; - font-size: 50px; - color: #4D8D99; -} - -#logo h1 a { - color: #F0E9E9; -} - -#logo p { - margin: 0px; - padding: 0px; - font-size: 26px; -} - -#logo a { - border: none; - background: none; - text-decoration: none; - color: #34312C; -} - -/* Search */ - -#search { - width: 280px; - height: 50px; - padding: 20px 0px 0px 0px; - background: url('../images/img05.jpg') no-repeat left 15px; -} - -#search form { - margin: 0px 0px 0px 0px; - padding: 0px 0px 0px 0px; -} - -#search fieldset { - margin: 0; - padding: 0; - border: none; -} - -#search-text { - width: 190px; - padding: 0px 5px 2px 10px; - border: none; - background: none; - text-transform: lowercase; - font: normal 11px Arial, Helvetica, sans-serif; - color: #34312C; -} - -#search-submit { - width: 70px; - height: 22px; - border: none; - border: none; - background: none; - text-indent: -99999px; - color: #34312C; -} - -/* Menu */ - -#menu { - width: 280px; - margin: 20px auto 20px auto; - padding: 0; -} - -#menu ul { - margin: 0; - padding: 50px 0px 0px 0px; - list-style: none; - line-height: normal; -} - -#menu li { - border-bottom: 1px dashed #191918; -} - -#menu a { - display: block; - width: 260px; - height: 27px; - margin: 4px 0px; - padding: 8px 0px 0px 20px; - text-decoration: none; - text-transform: capitalize; - font-family: Arial, Helvetica, sans-serif; - font-size: 14px; - font-weight: normal; - color: #FFF; -} - -#menu a:hover, #menu .current_page_item a { - background: url('../images/img06.jpg') no-repeat left top; - text-decoration: none; -} - -#menu .current_page_item a { -} - -/* Page */ - -#page { - width: 1000px; - margin: 0 auto; - background: url('../images/img04.jpg') repeat-y left top; -} - -#page-bgtop { - background: url('../images/img02.jpg') no-repeat left top; -} - -#page-bgbtm { - overflow: hidden; - width: 920px; - padding: 20px 40px 20px 40px; - background: url(images/img03.jpg) no-repeat left bottom; -} -/* Content */ - -#content { - float: right; - width: 520px; - padding: 70px 30px 0px 60px; -} - -.post { - margin-bottom: 40px; -} - -.post .title { - padding: 0px 0px 0px 0px; - font-family: Georgia, "Times New Roman", Times, serif; - letter-spacing: -.5px; -} - -.post .title a { - color: #52483E; - border: none; -} - -.post .meta { - margin-bottom: 0px; - padding: 10px 0px 0px 0px; - text-align: left; - font-family: Arial, Helvetica, sans-serif; - font-size: 13px; - font-weight: bold; -} - -.post .meta .date { - float: left; -} - -.post .meta .posted { - float: right; -} - -.post .meta a { -} - -.post .entry { - padding: 0px 0px 20px 0px; - border-bottom: 1px dotted #99938B; - text-align: justify; -} -.post .entry dt { - font-weight:bold ; -} - -.post img { - margin:10px; - border:black; -} -.summary img{ - display:none -} - -.entry h2{ - font-size: 1.6em; - color: #36302a; -} - -.entry h3{ - font-size: 1.2em; - color: #36302a; -} -h2.title { - font-size:2.8em; -} - -.highlight{ - background:black; - padding:2px; -} - -.highlight pre{ - color:white; -} - -.highlight{ - overflow:auto; -} - -.links { - padding-top: 20px; - font-size: 12px; - font-weight: bold; -} - -/* Sidebar */ - -#sidebar { - float: left; - width: 280px; - margin: 0px; - padding: 0px 0px 80px 10px; - color: #787878; -} - -#sidebar ul { - margin: 0; - padding: 0; - list-style: none; -} - -#sidebar li { - margin: 0; - padding: 0; -} - -#sidebar li ul { - margin: 0px 0px 0px 20px; - padding-bottom: 30px; -} - -#sidebar li li { - line-height: 35px; - border-bottom: 1px dashed #191918; - border-left: none; -} - -#sidebar li li span { - display: block; - margin-top: -20px; - padding: 0; - font-size: 11px; - font-style: italic; -} - -#sidebar li li a { - color: #787878; -} - -#sidebar li li a:hover { - color: #F0E9E9; -} - -#sidebar h2 { - height: 38px; - letter-spacing: -.5px; - font-size: 1.8em; -} - -#sidebar p { - margin: 0 0px; - padding: 0px 20px 20px 20px; -} - -#sidebar a { - border: none; -} - -#sidebar a:hover { -} - -/* Calendar */ - -#calendar { -} - -#calendar_wrap { - padding: 20px; -} - -#calendar table { - width: 100%; -} - -#calendar tbody td { - text-align: center; -} - -#calendar #next { - text-align: right; -} - -/* Footer */ - -#footer { - width: 920px; - height: 80px; - margin: 0 auto; - padding: 0px 0 15px 310px; - font-family: Arial, Helvetica, sans-serif; -} - -#footer p { - margin: 0; - padding-top: 20px; - line-height: normal; - font-size: 9px; - text-transform: uppercase; - text-align: center; - color: #69635E; -} - -#footer a { - color: #474440; -} diff --git a/pelican/themes/brownstone/static/images/img01.jpg b/pelican/themes/brownstone/static/images/img01.jpg deleted file mode 100644 index d417a5c0..00000000 Binary files a/pelican/themes/brownstone/static/images/img01.jpg and /dev/null differ diff --git a/pelican/themes/brownstone/static/images/img02.jpg b/pelican/themes/brownstone/static/images/img02.jpg deleted file mode 100644 index c4071c10..00000000 Binary files a/pelican/themes/brownstone/static/images/img02.jpg and /dev/null differ diff --git a/pelican/themes/brownstone/static/images/img03.jpg b/pelican/themes/brownstone/static/images/img03.jpg deleted file mode 100644 index bcb88b65..00000000 Binary files a/pelican/themes/brownstone/static/images/img03.jpg and /dev/null differ diff --git a/pelican/themes/brownstone/static/images/img04.jpg b/pelican/themes/brownstone/static/images/img04.jpg deleted file mode 100644 index ffb54f7c..00000000 Binary files a/pelican/themes/brownstone/static/images/img04.jpg and /dev/null differ diff --git a/pelican/themes/brownstone/static/images/img05.jpg b/pelican/themes/brownstone/static/images/img05.jpg deleted file mode 100644 index 5723f783..00000000 Binary files a/pelican/themes/brownstone/static/images/img05.jpg and /dev/null differ diff --git a/pelican/themes/brownstone/static/images/img06.jpg b/pelican/themes/brownstone/static/images/img06.jpg deleted file mode 100644 index 6a93cf2f..00000000 Binary files a/pelican/themes/brownstone/static/images/img06.jpg and /dev/null differ diff --git a/pelican/themes/brownstone/templates/analytics.html b/pelican/themes/brownstone/templates/analytics.html deleted file mode 100644 index f19c7a6f..00000000 --- a/pelican/themes/brownstone/templates/analytics.html +++ /dev/null @@ -1,11 +0,0 @@ -{% if GOOGLE_ANALYTICS %} - - -{% endif %} diff --git a/pelican/themes/brownstone/templates/archives.html b/pelican/themes/brownstone/templates/archives.html deleted file mode 100644 index a023ecee..00000000 --- a/pelican/themes/brownstone/templates/archives.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends "base.html" %} -{% block title %}Archives de {{ SITENAME }}{% endblock %} -{% block content %} -
-
-
-

Archives de {{ SITENAME }}

- {% for article in dates %} -
{{ article.date.strftime('%a %d %B %Y') }}
-
{{ article.title }}
-
Catégorie : {{ article.category }}
- {% endfor %} -
-
- -
 
-
- -{% endblock %} diff --git a/pelican/themes/brownstone/templates/article.html b/pelican/themes/brownstone/templates/article.html deleted file mode 100644 index 0467b64c..00000000 --- a/pelican/themes/brownstone/templates/article.html +++ /dev/null @@ -1,35 +0,0 @@ -{% extends "base.html" %} -{% block title %}{{ article.title }}{% endblock %} -{% block content %} -
-
-

{{ article.title }}

-

Le {{ article.date.strftime('%a %d %B %Y') }} Par {{ article.author }}  | Catégorie : {{ article.category }}

-

Tags : {% for tag in article.tags %} -{{ tag }} / -{% endfor %}

-
 
-
- {{ article.content }} - {% include 'twitter.html' %} -
-
- -
 
- {% if DISQUS_SITENAME %} -
-

Commentaires !

-
- -
- {% endif %} -
- -{% endblock %} diff --git a/pelican/themes/brownstone/templates/base.html b/pelican/themes/brownstone/templates/base.html deleted file mode 100644 index cd7cc7b3..00000000 --- a/pelican/themes/brownstone/templates/base.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - -{% block title %}{{ SITENAME }}{%endblock%} - - -{% if FEED_RSS %} - -{% endif %} - - -
-
-
-
- {% block content %} - {% endblock %} - - -
 
-
-
-
- - - -{% include 'analytics.html' %} - - - diff --git a/pelican/themes/brownstone/templates/categories.html b/pelican/themes/brownstone/templates/categories.html deleted file mode 100644 index 9e9bea89..00000000 --- a/pelican/themes/brownstone/templates/categories.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends "base.html" %} -{% block content %} -
-
- {% if articles %} - {% for article in articles %} - {% if loop.index == 1 %} -
    - {% for category, articles in categories %} -
  • {{ category }}
  • - {% endfor %} -
- {% endif %} - {% endfor %} - {% endif %} -
-
-{% endblock %} diff --git a/pelican/themes/brownstone/templates/category.html b/pelican/themes/brownstone/templates/category.html deleted file mode 100644 index 56f8e93e..00000000 --- a/pelican/themes/brownstone/templates/category.html +++ /dev/null @@ -1,2 +0,0 @@ -{% extends "index.html" %} -{% block title %}{{ SITENAME }} - {{ category }}{% endblock %} diff --git a/pelican/themes/brownstone/templates/index.html b/pelican/themes/brownstone/templates/index.html deleted file mode 100644 index 147ea006..00000000 --- a/pelican/themes/brownstone/templates/index.html +++ /dev/null @@ -1,43 +0,0 @@ -{% extends "base.html" %} -{% block content_title %}{% endblock %} -{% block content %} - {% if articles %} - {% for article in articles %} - {% if loop.index == 1 %} -
-
-

{{ article.title }}

-

Le {{ article.date.strftime('%a %d %B %Y') }} Par {{ article.author }}  | Catégorie : {{ article.category }}

-

Tags : {% for tag in article.tags %} -{{ tag }} / -{% endfor %}

-
 
-
- {{ article.content }} - {% include 'twitter.html' %} -
-
- {% if loop.length > 1 %} -
-

Autres articles

-
- {% endif %} - {% else %} -
-

{{ article.title }}

-

Le {{ article.date.strftime('%a %d %B %Y') }}Par {{ article.author }}

-
 
-
- {{ article.summary }} - Lire la suite … -
-
- {% endif %} - {% endfor %} - {% else %} -
-
- {% endif %} -
 
-
- {% endblock content %} diff --git a/pelican/themes/brownstone/templates/page.html b/pelican/themes/brownstone/templates/page.html deleted file mode 100644 index 6181ea98..00000000 --- a/pelican/themes/brownstone/templates/page.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends "base.html" %} -{% block title %}{{ page.title }}{% endblock %} -{% block content %} -
-
-

{{ page.title }}

- {% if PDF_PROCESSOR %}get - the pdf{% endif %} -
 
-
- {{ page.content }} - {% include 'twitter.html' %} -
-
-
- -{% endblock %} diff --git a/pelican/themes/brownstone/templates/tag.html b/pelican/themes/brownstone/templates/tag.html deleted file mode 100644 index 68cdcba6..00000000 --- a/pelican/themes/brownstone/templates/tag.html +++ /dev/null @@ -1,2 +0,0 @@ -{% extends "index.html" %} -{% block title %}{{ SITENAME }} - {{ tag }}{% endblock %} diff --git a/pelican/themes/brownstone/templates/tags.html b/pelican/themes/brownstone/templates/tags.html deleted file mode 100644 index a950663c..00000000 --- a/pelican/themes/brownstone/templates/tags.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends "base.html" %} -{% block content %} -
-
-
    -{% for tag, articles in tags %} -
  • {{ tag }}
  • -{% endfor %} -
-
-
-{% endblock %} diff --git a/pelican/themes/brownstone/templates/twitter.html b/pelican/themes/brownstone/templates/twitter.html deleted file mode 100644 index 94a9ba9c..00000000 --- a/pelican/themes/brownstone/templates/twitter.html +++ /dev/null @@ -1,3 +0,0 @@ -{% if TWITTER_USERNAME %} - -{% endif %} diff --git a/pelican/themes/martyalchin/static/css/style.css b/pelican/themes/martyalchin/static/css/style.css deleted file mode 100644 index 7ea07917..00000000 --- a/pelican/themes/martyalchin/static/css/style.css +++ /dev/null @@ -1,404 +0,0 @@ -/* Resets to avoid browser differences */ - -body, button, div, fieldset, form, h1, h2, h3, input, label, li, p, pre, td, textarea, .typygmentdown { - margin: 0; - padding: 0; - text-align: justify; - font-family: Georgia, serif; - font-size: 100%; - line-height: 1.25; - letter-spacing: 0; - border: none; - background: none; -} - -/* Overall page layout */ - -body { - background: white; - color: black; - color: #303030; -} - -@media screen { - body { - width: 700px; - margin: 20px auto; - } -} - -@media print { - body { - margin: 0 2em; - } -} - -/* Headings */ - -h1, h2, h3, h4, h5, h6, .info, .info p { - font-family: Times, serif; - font-weight: normal; - page-break-inside: avoid; -} - -h1 .caps, h2 .caps, h3 .caps { - letter-spacing: -.05em; -} - -h1 { - font-family: Times, serif; - text-align: center; - font-size: 2.25em; - line-height: 1.111; - padding-right: 0.08em; - letter-spacing: -.07em; -} - -h2 { - margin-top: 0.714em; - font-size: 1.75em; - line-height: 0.714; - letter-spacing: -.05em; -} - -h3 { - margin-top: 0.926em; - font-size: 1.35em; - line-height: 0.926; - letter-spacing: -.03em; -} - -h1 .dquo, h2 .dquo, h3 .dquo, h4 .dquo, h5 .dquo, h6 .dquo { - margin-left: -.4em; -} - -.info, .info p { - text-align: center; - letter-spacing: -.03em; -} - -.info p { - margin: 0; -} - -.info img.g { - width: 24px; - height: 24px; - margin: -7px 0; -} - -#home h2 a[href*="http://"] { - padding-right: 28px; - background: url("/static/link.png") right center no-repeat; -} - -#home h2 a[href*="http://"]:visited { - padding-right: 28px; - background: url("/static/visited.png") right center no-repeat; -} - -h2 + p.published { - float: right; - margin-top: -1.25em; -} - -.copyright { - margin: 1.25em 0; -} - -/* Page text */ - -p, p[class] + p { - margin-top: 1.25em; - widows: 2; - orphans: 2; - text-indent: 0; - clear: left; -} - -p + p { - text-indent: 1.5em; - margin-top: 0; -} - -p ~ img { - display: block; - margin: 1.25em auto; -} - -.caps { - letter-spacing: 0.1em; - font-size: 75%; -} - -abbr { - border-bottom: 1px dotted black; -} - -blockquote { - margin: 0 1em; - font-style: italic; - letter-spacing: -0.0625em; -} - -blockquote em { - font-style: normal; - letter-spacing: 0; -} - -div.image { - text-align: center; - margin: 1.25em 0; -} - -img { - border: none; -} - - - -.side { - position: absolute; - width: 150px; - height: auto; - margin-left: 710px; -} - -.left.side { - margin-left: -160px; -} - -.right.side { - margin-left: 710px; -} - -@media screen { - h1 a, h2 a, h3 a, .info a { - text-decoration: none; - } - - a:link { - color: #85ac40; - } - - a:visited { - color: #61883b; - } - - ::selection { - background: #dcff9d; - } - - ::-moz-selection { - background: #e2ffaf; - } -} - -@media print { - a { - color: inherit; - text-decoration: none; - } - - abbr { - border-bottom: none; - } -} - -/* Lists */ - -ul, ol { - margin: 1.25em 0 1.25em -1.5em; - padding-left: 1.5em; -} - -ul ul, ul ol, ol ol, ol ul { - margin: 0; -} - -ul li { - list-style: disc; -} - -li p { - margin: 0; -} - -/* Code */ - -pre { - margin-top: 1.47em; - font-family: Courier; - font-size: .85em; - line-height: 1.47; - overflow: visible; -} - -code { - font-family: Courier; - font-size: .85em; - line-height: 1; -} - -.typygmentdown .c { - font-style: italic; -} - -.typygmentdown .k, .typygmentdown .ow { - color: #404040; -} - -.typygmentdown .c, .typygmentdown .sd { - color: #808080; -} - -/* Comments */ - -#comment-list { - margin: 0; - padding: 0; -} - -#comment-list li { - padding-bottom: 1.25em; -} - -#comment-list cite { - font-style: normal; -} - -#comment-list cite + blockquote { - margin-top: 0; -} - -#comment-list blockquote { - margin: 0; -} - -#comment-list p { - margin-top: 1.25em; - text-indent: 0; -} - -#comment-form th { - width: 25%; -} - -#comment-form input, #comment-form select, #comment-form textarea { - width: 100%; -} - -@media print { - #comment-list, #comment-form { - display: none; - } -} - -/* Friends */ - -#friends li { - list-style: none; - margin-left: 0; - padding-left: 0; -} - -#friends a[rel] { - margin-left: 20px; -} - -#friends a[rel~="colleague"] { - background: url("/static/dj.png") left center no-repeat; - margin-left: 0; - padding-left: 20px; -} - -/* Forms */ - -form, form p { - text-indent: 0; - text-align: left; -} - -from th, form td { - margin: 0; - padding: 0; -} - -input, select, textarea { - background: white; - line-height: 1.5; -} - -input[type="submit"], button { - border: 1px outset; - text-align: center; - background: #85ac40; - padding: .2em; -} - -input[type="text"], textarea { - vertical-align: top; - border: 1px solid #e0e0e0; -} - -input[type="text"], select { - width: 15em; -} - -textarea { - width: 45em; - height: 7.5em; - overflow: auto; -} - -#honeypot { - display: none; -} - -/* Tables */ - -table { - border-collapse: collapse; - border: none; - margin: 1.25em auto; -} - -caption { - border-bottom: 1px solid #303030; -} - -thead th { - border-bottom: 1px solid #303030; -} - -tfoot th, -tfoot td { - border-top: 1px solid #303030; -} - -th[scope="row"], -th[scope="col"] { - text-align: left; -} - -tbody + tbody th, tbody + tbody td { - border-top: 1px solid #d0d0d0; -} - -tbody + tbody tr + tr th, -tbody + tbody tr + tr td, -tfoot tr + tr th, -tfoot tr + tr td { - border-top: none; -} - -th, td { - padding: 0 0.5em; - font-weight: normal; - vertical-align: top; -} - -table.numeric td, table.numeric th[scope="col"] { - text-align: right; -} - diff --git a/pelican/themes/martyalchin/templates/archives.html b/pelican/themes/martyalchin/templates/archives.html deleted file mode 100644 index e69de29b..00000000 diff --git a/pelican/themes/martyalchin/templates/article.html b/pelican/themes/martyalchin/templates/article.html deleted file mode 100644 index c7711a75..00000000 --- a/pelican/themes/martyalchin/templates/article.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends "base.html" %} -{% block title %}{{ article.title }}{%endblock%} -{% block content %} -

{{ article.title }}

-
- {% if article.author %} - By {{ article.author }} - {% endif %} - on {{ article.date.strftime('%a %d %B %Y') }} - about {{ article.category }} -
- {{ article.content }} -{% endblock %} diff --git a/pelican/themes/martyalchin/templates/base.html b/pelican/themes/martyalchin/templates/base.html deleted file mode 100644 index eea18f9b..00000000 --- a/pelican/themes/martyalchin/templates/base.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - {% block title %}{{ SITENAME }}{%endblock%} - - - - - - {% block content %} {% endblock %} - - - - diff --git a/pelican/themes/martyalchin/templates/categories.html b/pelican/themes/martyalchin/templates/categories.html deleted file mode 100644 index e69de29b..00000000 diff --git a/pelican/themes/martyalchin/templates/category.html b/pelican/themes/martyalchin/templates/category.html deleted file mode 100644 index 8f9b6626..00000000 --- a/pelican/themes/martyalchin/templates/category.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "base.html" %} -{% block title %}{{ category }}{%endblock%} -

{{ category }}

-
-{% for article in articles %} -

{{ article.title }}

-

{{ article.date.strftime('%a %d %B %Y') }}

-{{ article.summary }} -{% endfor %} diff --git a/pelican/themes/martyalchin/templates/index.html b/pelican/themes/martyalchin/templates/index.html deleted file mode 100644 index eeaa8a7a..00000000 --- a/pelican/themes/martyalchin/templates/index.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "base.html" %} -{% block content %} -

{{ SITENAME }}

- {% if SITESUBTITLE %}
{{ SITESUBTITLE }}
{% endif %} - {% for article in articles %} -

{{ article.title }}

-

{{ article.date.strftime('%a %d %B %Y') }}

- {{ article.summary }} - {% endfor %} -{% endblock %} diff --git a/pelican/themes/martyalchin/templates/page.html b/pelican/themes/martyalchin/templates/page.html deleted file mode 100644 index 727c762c..00000000 --- a/pelican/themes/martyalchin/templates/page.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "base.html" %} -{% block title %}{{ page.title }}{%endblock%} -{% block content %} -

{{ page.title }}

- {{ page.content }} -{% endblock %} - diff --git a/pelican/themes/martyalchin/templates/tag.html b/pelican/themes/martyalchin/templates/tag.html deleted file mode 100644 index e69de29b..00000000 diff --git a/pelican/themes/martyalchin/templates/tags.html b/pelican/themes/martyalchin/templates/tags.html deleted file mode 100644 index e69de29b..00000000 diff --git a/pelican/themes/notmyidea/static/css/main.css b/pelican/themes/notmyidea/static/css/main.css index 0972ca0b..a3fd60f1 100644 --- a/pelican/themes/notmyidea/static/css/main.css +++ b/pelican/themes/notmyidea/static/css/main.css @@ -276,14 +276,6 @@ img.left, figure.left {float: right; margin: 0 0 2em 2em;} padding: .3em .25em; } -#extras li:last-child, -#extras li:last-child a {border: 0} - -#extras .blogroll li:nth-last-child(2), -#extras .blogroll li:nth-last-child(3), -#extras .blogroll li:nth-last-child(2) a, -#extras .blogroll li:nth-last-child(3) a {border: 0;} - #extras a:hover, #extras a:active {color: #fff;} /* Blogroll */ diff --git a/pelican/themes/notmyidea/templates/archives.html b/pelican/themes/notmyidea/templates/archives.html index 1644affb..5ba2c817 100644 --- a/pelican/themes/notmyidea/templates/archives.html +++ b/pelican/themes/notmyidea/templates/archives.html @@ -5,7 +5,7 @@
{% for article in dates %} -
{{ article.date.strftime('%a %d %B %Y') }}
+
{{ article.locale_date }}
{{ article.title }}
{% endfor %}
diff --git a/pelican/themes/notmyidea/templates/article.html b/pelican/themes/notmyidea/templates/article.html index 8b5e5bae..14fffe4d 100644 --- a/pelican/themes/notmyidea/templates/article.html +++ b/pelican/themes/notmyidea/templates/article.html @@ -7,18 +7,7 @@ rel="bookmark" title="Permalink to {{ article.title }}">{{ article.title }} {% include 'twitter.html' %}
- + {% include 'article_infos.html' %} {{ article.content }}
{% if DISQUS_SITENAME %} diff --git a/pelican/themes/notmyidea/templates/article_infos.html b/pelican/themes/notmyidea/templates/article_infos.html new file mode 100644 index 00000000..3a028a1c --- /dev/null +++ b/pelican/themes/notmyidea/templates/article_infos.html @@ -0,0 +1,14 @@ + diff --git a/pelican/themes/notmyidea/templates/base.html b/pelican/themes/notmyidea/templates/base.html index 1ec6fe5e..6a5cfaf5 100644 --- a/pelican/themes/notmyidea/templates/base.html +++ b/pelican/themes/notmyidea/templates/base.html @@ -9,6 +9,7 @@ {% endif %} + {% include 'skribit_tab_script.html' %} @@ -53,6 +54,7 @@
{% endif %} + {% include 'skribit_widget_script.html' %} {% if SOCIAL %}