diff --git a/.travis.yml b/.travis.yml
index 3a309d0d..19cb7e89 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,12 +4,11 @@ python:
- "3.2"
before_install:
- sudo apt-get update -qq
- - sudo apt-get install -qq --no-install-recommends asciidoc ruby-sass
+ - sudo apt-get install -qq --no-install-recommends asciidoc
install:
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then ln -s /usr/share/asciidoc/asciidocapi.py ~/virtualenv/python2.7/lib/python2.7/site-packages/; fi
- pip install nose mock --use-mirrors
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install --use-mirrors unittest2; else pip install --use-mirrors unittest2py3k; fi
- pip install . --use-mirrors
- pip install --use-mirrors Markdown
- - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install --use-mirrors webassets cssmin; fi
script: nosetests -s pelican
diff --git a/dev_requirements.txt b/dev_requirements.txt
index e0189d35..fa2634a0 100644
--- a/dev_requirements.txt
+++ b/dev_requirements.txt
@@ -6,4 +6,3 @@ Markdown
BeautifulSoup4
lxml
typogrify
-webassets
diff --git a/docs/plugins.rst b/docs/plugins.rst
index 857180f0..21a962e2 100644
--- a/docs/plugins.rst
+++ b/docs/plugins.rst
@@ -6,9 +6,6 @@ Plugins
Beginning with version 3.0, Pelican supports plugins. Plugins are a way to add
features to Pelican without having to directly modify the Pelican core.
-Pelican is shipped with a set of bundled plugins, but you can easily implement
-your own. This page describes how to use and create plugins.
-
How to use plugins
==================
@@ -16,12 +13,12 @@ To load plugins, you have to specify them in your settings file. There are two
ways to do so. The first method is to specify strings with the path to the
callables::
- PLUGINS = ['pelican.plugins.gravatar',]
+ PLUGINS = ['package.myplugin',]
Alternatively, another method is to import them and add them to the list::
- from pelican.plugins import gravatar
- PLUGINS = [gravatar,]
+ from package import myplugin
+ PLUGINS = [myplugin,]
If your plugins are not in an importable path, you can specify a ``PLUGIN_PATH``
in the settings. ``PLUGIN_PATH`` can be an absolute path or a path relative to
@@ -30,6 +27,17 @@ the settings file::
PLUGIN_PATH = "plugins"
PLUGINS = ["list", "of", "plugins"]
+Where to find plugins
+=====================
+
+We maintain a separate repository of plugins for people to share and use.
+Please see the `pelican-plugins`_ repository for the official place for plugins.
+
+.. _pelican-plugins: https://github.com/getpelican/pelican-plugins
+
+Please note that while we will give best effort, the submitted plugins are all
+community driven and supported.
+
How to create plugins
=====================
@@ -96,311 +104,3 @@ request if you need them!
def register():
signals.content_object_init.connect(test, sender=contents.Article)
-
-
-
-List of plugins
-===============
-
-The following plugins are currently included with Pelican:
-
-* `Asset management`_ ``pelican.plugins.assets``
-* `GitHub activity`_ ``pelican.plugins.github_activity``
-* `Global license`_ ``pelican.plugins.global_license``
-* `Gravatar`_ ``pelican.plugins.gravatar``
-* `Gzip cache`_ ``pelican.plugins.gzip_cache``
-* `HTML tags for reStructuredText`_ ``pelican.plugins.html_rst_directive``
-* `Related posts`_ ``pelican.plugins.related_posts``
-* `Sitemap`_ ``pelican.plugins.sitemap``
-* `Summary`_ ``pelican.plugins.summary``
-
-Ideas for plugins that haven't been written yet:
-
-* Tag cloud
-* Translation
-
-Plugin descriptions
-===================
-
-Asset management
-----------------
-
-This plugin allows you to use the `Webassets`_ module to manage assets such as
-CSS and JS files. The module must first be installed::
-
- pip install webassets
-
-The Webassets module allows you to perform a number of useful asset management
-functions, including:
-
-* CSS minifier (``cssmin``, ``yui_css``, ...)
-* CSS compiler (``less``, ``sass``, ...)
-* JS minifier (``uglifyjs``, ``yui_js``, ``closure``, ...)
-
-Others filters include gzip compression, integration of images in CSS via data
-URIs, and more. Webassets can also append a version identifier to your asset
-URL to convince browsers to download new versions of your assets when you use
-far-future expires headers. Please refer to the `Webassets documentation`_ for
-more information.
-
-When used with Pelican, Webassets is configured to process assets in the
-``OUTPUT_PATH/theme`` directory. You can use Webassets in your templates by
-including one or more template tags. The Jinja variable ``{{ ASSET_URL }}`` can
-be used in templates and is relative to the ``theme/`` url. The
-``{{ ASSET_URL }}`` variable should be used in conjunction with the
-``{{ SITEURL }}`` variable in order to generate URLs properly. For example:
-
-.. code-block:: jinja
-
- {% assets filters="cssmin", output="css/style.min.css", "css/inuit.css", "css/pygment-monokai.css", "css/main.css" %}
-
- {% endassets %}
-
-... will produce a minified css file with a version identifier that looks like:
-
-.. code-block:: html
-
-
-
-These filters can be combined. Here is an example that uses the SASS compiler
-and minifies the output:
-
-.. code-block:: jinja
-
- {% assets filters="sass,cssmin", output="css/style.min.css", "css/style.scss" %}
-
- {% endassets %}
-
-Another example for Javascript:
-
-.. code-block:: jinja
-
- {% assets filters="uglifyjs,gzip", output="js/packed.js", "js/jquery.js", "js/base.js", "js/widgets.js" %}
-
- {% endassets %}
-
-The above will produce a minified and gzipped JS file:
-
-.. code-block:: html
-
-
-
-Pelican's debug mode is propagated to Webassets to disable asset packaging
-and instead work with the uncompressed assets.
-
-Many of Webasset's available compilers have additional configuration options
-(i.e. 'Less', 'Sass', 'Stylus', 'Closure_js'). You can pass these options to
-Webassets using the ``ASSET_CONFIG`` in your settings file.
-
-The following will handle Google Closure's compilation level and locate
-LessCSS's binary:
-
-.. code-block:: python
-
- ASSET_CONFIG = (('closure_compressor_optimization', 'WHITESPACE_ONLY'),
- ('less_bin', 'lessc.cmd'), )
-
-.. _Webassets: https://github.com/miracle2k/webassets
-.. _Webassets documentation: http://webassets.readthedocs.org/en/latest/builtin_filters.html
-
-
-GitHub activity
----------------
-
-This plugin makes use of the `feedparser`_ library that you'll need to
-install.
-
-Set the ``GITHUB_ACTIVITY_FEED`` parameter to your GitHub activity feed.
-For example, to track Pelican project activity, the setting would be::
-
- GITHUB_ACTIVITY_FEED = 'https://github.com/getpelican.atom'
-
-On the template side, you just have to iterate over the ``github_activity``
-variable, as in this example::
-
- {% if GITHUB_ACTIVITY_FEED %}
-
-
Github Activity
-
-
- {% for entry in github_activity %}
-
{{ entry[0] }} {{ entry[1] }}
- {% endfor %}
-
-
- {% endif %}
-
-``github_activity`` is a list of lists. The first element is the title,
-and the second element is the raw HTML from GitHub.
-
-.. _feedparser: https://crate.io/packages/feedparser/
-
-Global license
---------------
-
-This plugin allows you to define a ``LICENSE`` setting and adds the contents of that
-license variable to the article's context, making that variable available to use
-from within your theme's templates.
-
-Gravatar
---------
-
-This plugin assigns the ``author_gravatar`` variable to the Gravatar URL and
-makes the variable available within the article's context. You can add
-``AUTHOR_EMAIL`` to your settings file to define the default author's email
-address. Obviously, that email address must be associated with a Gravatar
-account.
-
-Alternatively, you can provide an email address from within article metadata::
-
- :email: john.doe@example.com
-
-If the email address is defined via at least one of the two methods above,
-the ``author_gravatar`` variable is added to the article's context.
-
-Gzip cache
-----------
-
-Certain web servers (e.g., Nginx) can use a static cache of gzip-compressed
-files to prevent the server from compressing files during an HTTP call. Since
-compression occurs at another time, these compressed files can be compressed
-at a higher compression level for increased optimization.
-
-The ``gzip_cache`` plugin compresses all common text type files into a ``.gz``
-file within the same directory as the original file.
-
-HTML tags for reStructuredText
-------------------------------
-
-This plugin allows you to use HTML tags from within reST documents. Following
-is a usage example, which is in this case a contact form::
-
- .. html::
-
-
-
-Related posts
--------------
-
-This plugin adds the ``related_posts`` variable to the article's context.
-By default, up to 5 articles are listed. You can customize this value by
-defining ``RELATED_POSTS_MAX`` in your settings file::
-
- RELATED_POSTS_MAX = 10
-
-You can then use the ``article.related_posts`` variable in your templates.
-For example::
-
- {% if article.related_posts %}
-
- {% for related_post in article.related_posts %}
-
- {% endif %}
-
-Sitemap
--------
-
-The sitemap plugin generates plain-text or XML sitemaps. You can use the
-``SITEMAP`` variable in your settings file to configure the behavior of the
-plugin.
-
-The ``SITEMAP`` variable must be a Python dictionary and can contain three keys:
-
-- ``format``, which sets the output format of the plugin (``xml`` or ``txt``)
-
-- ``priorities``, which is a dictionary with three keys:
-
- - ``articles``, the priority for the URLs of the articles and their
- translations
-
- - ``pages``, the priority for the URLs of the static pages
-
- - ``indexes``, the priority for the URLs of the index pages, such as tags,
- author pages, categories indexes, archives, etc...
-
- All the values of this dictionary must be decimal numbers between ``0`` and ``1``.
-
-- ``changefreqs``, which is a dictionary with three items:
-
- - ``articles``, the update frequency of the articles
-
- - ``pages``, the update frequency of the pages
-
- - ``indexes``, the update frequency of the index pages
-
- Valid frequency values are ``always``, ``hourly``, ``daily``, ``weekly``, ``monthly``,
- ``yearly`` and ``never``.
-
-If a key is missing or a value is incorrect, it will be replaced with the
-default value.
-
-The sitemap is saved in ``/sitemap.``.
-
-.. note::
- ``priorities`` and ``changefreqs`` are information for search engines.
- They are only used in the XML sitemaps.
- For more information:
-
-**Example**
-
-Here is an example configuration (it's also the default settings):
-
-.. code-block:: python
-
- PLUGINS=['pelican.plugins.sitemap',]
-
- SITEMAP = {
- 'format': 'xml',
- 'priorities': {
- 'articles': 0.5,
- 'indexes': 0.5,
- 'pages': 0.5
- },
- 'changefreqs': {
- 'articles': 'monthly',
- 'indexes': 'daily',
- 'pages': 'monthly'
- }
- }
-
-.. _plugin-summary:
-
-Summary
--------------
-
-This plugin allows easy, variable length summaries directly embedded into the
-body of your articles. It introduces two new settings: ``SUMMARY_BEGIN_MARKER``
-and ``SUMMARY_END_MARKER``: strings which can be placed directly into an article
-to mark the beginning and end of a summary. When found, the standard
-``SUMMARY_MAX_LENGTH`` setting will be ignored. The markers themselves will also
-be removed from your articles before they are published. The default values
-are ```` and ````.
-For example::
-
- Title: My super title
- Date: 2010-12-03 10:20
- Tags: thats, awesome
- Category: yeah
- Slug: my-super-post
- Author: Alexis Metaireau
-
- This is the content of my super blog post.
-
- and this content occurs after the summary.
-
-Here, the summary is taken to be the first line of the post. Because no
-beginning marker was found, it starts at the top of the body. It is possible
-to leave out the end marker instead, in which case the summary will start at the
-beginning marker and continue to the end of the body.
-
diff --git a/pelican/plugins/__init__.py b/pelican/plugins/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/pelican/plugins/assets.py b/pelican/plugins/assets.py
deleted file mode 100644
index 5708224c..00000000
--- a/pelican/plugins/assets.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-"""
-Asset management plugin for Pelican
-===================================
-
-This plugin allows you to use the `webassets`_ module to manage assets such as
-CSS and JS files.
-
-The ASSET_URL is set to a relative url to honor Pelican's RELATIVE_URLS
-setting. This requires the use of SITEURL in the templates::
-
-
-
-.. _webassets: https://webassets.readthedocs.org/
-
-"""
-
-import os
-import logging
-
-from pelican import signals
-from webassets import Environment
-from webassets.ext.jinja2 import AssetsExtension
-
-
-def add_jinja2_ext(pelican):
- """Add Webassets to Jinja2 extensions in Pelican settings."""
-
- pelican.settings['JINJA_EXTENSIONS'].append(AssetsExtension)
-
-
-def create_assets_env(generator):
- """Define the assets environment and pass it to the generator."""
-
- assets_url = 'theme/'
- assets_src = os.path.join(generator.output_path, 'theme')
- generator.env.assets_environment = Environment(assets_src, assets_url)
-
- if 'ASSET_CONFIG' in generator.settings:
- for item in generator.settings['ASSET_CONFIG']:
- generator.env.assets_environment.config[item[0]] = item[1]
-
- logger = logging.getLogger(__name__)
- if logging.getLevelName(logger.getEffectiveLevel()) == "DEBUG":
- generator.env.assets_environment.debug = True
-
-
-def register():
- """Plugin registration."""
-
- signals.initialized.connect(add_jinja2_ext)
- signals.generator_init.connect(create_assets_env)
diff --git a/pelican/plugins/github_activity.py b/pelican/plugins/github_activity.py
deleted file mode 100644
index cc139efc..00000000
--- a/pelican/plugins/github_activity.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals, print_function
-"""
- Copyright (c) Marco Milanesi
-
- A plugin to list your Github Activity
- To enable it set in your pelican config file the GITHUB_ACTIVITY_FEED
- parameter pointing to your github activity feed.
-
- for example my personal activity feed is:
-
- https://github.com/kpanic.atom
-
- in your template just write a for in jinja2 syntax against the
- github_activity variable.
-
- i.e.
-
-
-
Github Activity
-
-
- {% for entry in github_activity %}
-
{{ entry[0] }} {{ entry[1] }}
- {% endfor %}
-
-
-
- github_activity is a list containing a list. The first element is the title
- and the second element is the raw html from github
-"""
-
-from pelican import signals
-
-
-class GitHubActivity():
- """
- A class created to fetch github activity with feedparser
- """
- def __init__(self, generator):
- try:
- import feedparser
- self.activities = feedparser.parse(
- generator.settings['GITHUB_ACTIVITY_FEED'])
- except ImportError:
- raise Exception("Unable to find feedparser")
-
- def fetch(self):
- """
- returns a list of html snippets fetched from github actitivy feed
- """
-
- entries = []
- for activity in self.activities['entries']:
- entries.append(
- [element for element in [activity['title'],
- activity['content'][0]['value']]])
-
- return entries
-
-
-def fetch_github_activity(gen, metadata):
- """
- registered handler for the github activity plugin
- it puts in generator.context the html needed to be displayed on a
- template
- """
-
- if 'GITHUB_ACTIVITY_FEED' in gen.settings.keys():
- gen.context['github_activity'] = gen.plugin_instance.fetch()
-
-
-def feed_parser_initialization(generator):
- """
- Initialization of feed parser
- """
-
- generator.plugin_instance = GitHubActivity(generator)
-
-
-def register():
- """
- Plugin registration
- """
- signals.article_generator_init.connect(feed_parser_initialization)
- signals.article_generate_context.connect(fetch_github_activity)
diff --git a/pelican/plugins/global_license.py b/pelican/plugins/global_license.py
deleted file mode 100644
index 9a0f5206..00000000
--- a/pelican/plugins/global_license.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from pelican import signals
-
-"""
-License plugin for Pelican
-==========================
-
-This plugin allows you to define a LICENSE setting and adds the contents of that
-license variable to the article's context, making that variable available to use
-from within your theme's templates.
-
-Settings:
----------
-
-Define LICENSE in your settings file with the contents of your default license.
-
-"""
-
-def add_license(generator, metadata):
- if 'license' not in metadata.keys()\
- and 'LICENSE' in generator.settings.keys():
- metadata['license'] = generator.settings['LICENSE']
-
-def register():
- signals.article_generate_context.connect(add_license)
diff --git a/pelican/plugins/gravatar.py b/pelican/plugins/gravatar.py
deleted file mode 100644
index 2b8520df..00000000
--- a/pelican/plugins/gravatar.py
+++ /dev/null
@@ -1,44 +0,0 @@
-import hashlib
-import six
-
-from pelican import signals
-"""
-Gravatar plugin for Pelican
-===========================
-
-This plugin assigns the ``author_gravatar`` variable to the Gravatar URL and
-makes the variable available within the article's context.
-
-Settings:
----------
-
-Add AUTHOR_EMAIL to your settings file to define the default author's email
-address. Obviously, that email address must be associated with a Gravatar
-account.
-
-Article metadata:
-------------------
-
-:email: article's author email
-
-If one of them are defined, the author_gravatar variable is added to the
-article's context.
-"""
-
-def add_gravatar(generator, metadata):
-
- #first check email
- if 'email' not in metadata.keys()\
- and 'AUTHOR_EMAIL' in generator.settings.keys():
- metadata['email'] = generator.settings['AUTHOR_EMAIL']
-
- #then add gravatar url
- if 'email' in metadata.keys():
- email_bytes = six.b(metadata['email']).lower()
- gravatar_url = "http://www.gravatar.com/avatar/" + \
- hashlib.md5(email_bytes).hexdigest()
- metadata["author_gravatar"] = gravatar_url
-
-
-def register():
- signals.article_generate_context.connect(add_gravatar)
diff --git a/pelican/plugins/gzip_cache.py b/pelican/plugins/gzip_cache.py
deleted file mode 100644
index 9080629e..00000000
--- a/pelican/plugins/gzip_cache.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright (c) 2012 Matt Layman
-'''A plugin to create .gz cache files for optimization.'''
-
-import gzip
-import logging
-import os
-
-from pelican import signals
-
-logger = logging.getLogger(__name__)
-
-# A list of file types to exclude from possible compression
-EXCLUDE_TYPES = [
- # Compressed types
- '.bz2',
- '.gz',
-
- # Audio types
- '.aac',
- '.flac',
- '.mp3',
- '.wma',
-
- # Image types
- '.gif',
- '.jpg',
- '.jpeg',
- '.png',
-
- # Video types
- '.avi',
- '.mov',
- '.mp4',
-]
-
-def create_gzip_cache(pelican):
- '''Create a gzip cache file for every file that a webserver would
- reasonably want to cache (e.g., text type files).
-
- :param pelican: The Pelican instance
- '''
- for dirpath, _, filenames in os.walk(pelican.settings['OUTPUT_PATH']):
- for name in filenames:
- if should_compress(name):
- filepath = os.path.join(dirpath, name)
- create_gzip_file(filepath)
-
-def should_compress(filename):
- '''Check if the filename is a type of file that should be compressed.
-
- :param filename: A file name to check against
- '''
- for extension in EXCLUDE_TYPES:
- if filename.endswith(extension):
- return False
-
- return True
-
-def create_gzip_file(filepath):
- '''Create a gzipped file in the same directory with a filepath.gz name.
-
- :param filepath: A file to compress
- '''
- compressed_path = filepath + '.gz'
-
- with open(filepath, 'rb') as uncompressed:
- try:
- logger.debug('Compressing: %s' % filepath)
- compressed = gzip.open(compressed_path, 'wb')
- compressed.writelines(uncompressed)
- except Exception as ex:
- logger.critical('Gzip compression failed: %s' % ex)
- finally:
- compressed.close()
-
-def register():
- signals.finalized.connect(create_gzip_cache)
-
diff --git a/pelican/plugins/html_rst_directive.py b/pelican/plugins/html_rst_directive.py
deleted file mode 100644
index 2b2bceb3..00000000
--- a/pelican/plugins/html_rst_directive.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-from docutils import nodes
-from docutils.parsers.rst import directives, Directive
-
-"""
-HTML tags for reStructuredText
-==============================
-
-Directives
-----------
-
-.. html::
-
- (HTML code)
-
-
-Example
--------
-
-A search engine:
-
-.. html::
-
-
-
-A contact form:
-
-.. html::
-
-
-
-"""
-
-
-class RawHtml(Directive):
- required_arguments = 0
- optional_arguments = 0
- final_argument_whitespace = True
- has_content = True
-
- def run(self):
- html = ' '.join(self.content)
- node = nodes.raw('', html, format='html')
- return [node]
-
-
-
-def register():
- directives.register_directive('html', RawHtml)
-
diff --git a/pelican/plugins/initialized.py b/pelican/plugins/initialized.py
deleted file mode 100644
index b4b5ab76..00000000
--- a/pelican/plugins/initialized.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals, print_function
-from pelican import signals
-
-def test(sender):
- print("%s initialized !!" % sender)
-
-def register():
- signals.initialized.connect(test)
diff --git a/pelican/plugins/related_posts.py b/pelican/plugins/related_posts.py
deleted file mode 100644
index 81999002..00000000
--- a/pelican/plugins/related_posts.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""
-Related posts plugin for Pelican
-================================
-
-Adds related_posts variable to article's context
-"""
-
-from pelican import signals
-from collections import Counter
-
-
-def add_related_posts(generator):
- # get the max number of entries from settings
- # or fall back to default (5)
- numentries = generator.settings.get('RELATED_POSTS_MAX', 5)
-
- for article in generator.articles:
- # no tag, no relation
- if not hasattr(article, 'tags'):
- continue
-
- # score = number of common tags
- scores = Counter()
- for tag in article.tags:
- scores += Counter(generator.tags[tag])
-
- # remove itself
- scores.pop(article)
-
- article.related_posts = [other for other, count
- in scores.most_common(numentries)]
-
-
-def register():
- signals.article_generator_finalized.connect(add_related_posts)
\ No newline at end of file
diff --git a/pelican/plugins/sitemap.py b/pelican/plugins/sitemap.py
deleted file mode 100644
index 8043baad..00000000
--- a/pelican/plugins/sitemap.py
+++ /dev/null
@@ -1,195 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-import collections
-import os.path
-
-from datetime import datetime
-from logging import warning, info
-from codecs import open
-
-from pelican import signals, contents
-
-TXT_HEADER = """{0}/index.html
-{0}/archives.html
-{0}/tags.html
-{0}/categories.html
-"""
-
-XML_HEADER = """
-
-"""
-
-XML_URL = """
-
-{0}/{1}
-{2}
-{3}
-{4}
-
-"""
-
-XML_FOOTER = """
-
-"""
-
-
-def format_date(date):
- if date.tzinfo:
- tz = date.strftime('%s')
- tz = tz[:-2] + ':' + tz[-2:]
- else:
- tz = "-00:00"
- return date.strftime("%Y-%m-%dT%H:%M:%S") + tz
-
-
-class SitemapGenerator(object):
-
- def __init__(self, context, settings, path, theme, output_path, *null):
-
- self.output_path = output_path
- self.context = context
- self.now = datetime.now()
- self.siteurl = settings.get('SITEURL')
-
- self.format = 'xml'
-
- self.changefreqs = {
- 'articles': 'monthly',
- 'indexes': 'daily',
- 'pages': 'monthly'
- }
-
- self.priorities = {
- 'articles': 0.5,
- 'indexes': 0.5,
- 'pages': 0.5
- }
-
- config = settings.get('SITEMAP', {})
-
- if not isinstance(config, dict):
- warning("sitemap plugin: the SITEMAP setting must be a dict")
- else:
- fmt = config.get('format')
- pris = config.get('priorities')
- chfreqs = config.get('changefreqs')
-
- if fmt not in ('xml', 'txt'):
- warning("sitemap plugin: SITEMAP['format'] must be `txt' or `xml'")
- warning("sitemap plugin: Setting SITEMAP['format'] on `xml'")
- elif fmt == 'txt':
- self.format = fmt
- return
-
- valid_keys = ('articles', 'indexes', 'pages')
- valid_chfreqs = ('always', 'hourly', 'daily', 'weekly', 'monthly',
- 'yearly', 'never')
-
- if isinstance(pris, dict):
- # We use items for Py3k compat. .iteritems() otherwise
- for k, v in pris.items():
- if k in valid_keys and not isinstance(v, (int, float)):
- default = self.priorities[k]
- warning("sitemap plugin: priorities must be numbers")
- warning("sitemap plugin: setting SITEMAP['priorities']"
- "['{0}'] on {1}".format(k, default))
- pris[k] = default
- self.priorities.update(pris)
- elif pris is not None:
- warning("sitemap plugin: SITEMAP['priorities'] must be a dict")
- warning("sitemap plugin: using the default values")
-
- if isinstance(chfreqs, dict):
- # .items() for py3k compat.
- for k, v in chfreqs.items():
- if k in valid_keys and v not in valid_chfreqs:
- default = self.changefreqs[k]
- warning("sitemap plugin: invalid changefreq `{0}'".format(v))
- warning("sitemap plugin: setting SITEMAP['changefreqs']"
- "['{0}'] on '{1}'".format(k, default))
- chfreqs[k] = default
- self.changefreqs.update(chfreqs)
- elif chfreqs is not None:
- warning("sitemap plugin: SITEMAP['changefreqs'] must be a dict")
- warning("sitemap plugin: using the default values")
-
-
-
- def write_url(self, page, fd):
-
- if getattr(page, 'status', 'published') != 'published':
- return
-
- page_path = os.path.join(self.output_path, page.url)
- if not os.path.exists(page_path):
- return
-
- lastmod = format_date(getattr(page, 'date', self.now))
-
- if isinstance(page, contents.Article):
- pri = self.priorities['articles']
- chfreq = self.changefreqs['articles']
- elif isinstance(page, contents.Page):
- pri = self.priorities['pages']
- chfreq = self.changefreqs['pages']
- else:
- pri = self.priorities['indexes']
- chfreq = self.changefreqs['indexes']
-
-
- if self.format == 'xml':
- fd.write(XML_URL.format(self.siteurl, page.url, lastmod, chfreq, pri))
- else:
- fd.write(self.siteurl + '/' + loc + '\n')
-
-
- def generate_output(self, writer):
- path = os.path.join(self.output_path, 'sitemap.{0}'.format(self.format))
-
- pages = self.context['pages'] + self.context['articles'] \
- + [ c for (c, a) in self.context['categories']] \
- + [ t for (t, a) in self.context['tags']] \
- + [ a for (a, b) in self.context['authors']]
-
- for article in self.context['articles']:
- pages += article.translations
-
- info('writing {0}'.format(path))
-
- with open(path, 'w', encoding='utf-8') as fd:
-
- if self.format == 'xml':
- fd.write(XML_HEADER)
- else:
- fd.write(TXT_HEADER.format(self.siteurl))
-
- FakePage = collections.namedtuple('FakePage',
- ['status',
- 'date',
- 'url'])
-
- for standard_page_url in ['index.html',
- 'archives.html',
- 'tags.html',
- 'categories.html']:
- fake = FakePage(status='published',
- date=self.now,
- url=standard_page_url)
- self.write_url(fake, fd)
-
- for page in pages:
- self.write_url(page, fd)
-
- if self.format == 'xml':
- fd.write(XML_FOOTER)
-
-
-def get_generators(generators):
- return SitemapGenerator
-
-
-def register():
- signals.get_generators.connect(get_generators)
diff --git a/pelican/plugins/summary.py b/pelican/plugins/summary.py
deleted file mode 100644
index 6822353c..00000000
--- a/pelican/plugins/summary.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import types
-
-from pelican import signals
-
-def initialized(pelican):
- from pelican.settings import _DEFAULT_CONFIG
- _DEFAULT_CONFIG.setdefault('SUMMARY_BEGIN_MARKER',
- '')
- _DEFAULT_CONFIG.setdefault('SUMMARY_END_MARKER',
- '')
- if pelican:
- pelican.settings.setdefault('SUMMARY_BEGIN_MARKER',
- '')
- pelican.settings.setdefault('SUMMARY_END_MARKER',
- '')
-
-def content_object_init(instance):
- # if summary is already specified, use it
- if 'summary' in instance.metadata:
- return
-
- def _get_content(self):
- content = self._content
- if self.settings['SUMMARY_BEGIN_MARKER']:
- content = content.replace(
- self.settings['SUMMARY_BEGIN_MARKER'], '', 1)
- if self.settings['SUMMARY_END_MARKER']:
- content = content.replace(
- self.settings['SUMMARY_END_MARKER'], '', 1)
- return content
- instance._get_content = types.MethodType(_get_content, instance)
-
- # extract out our summary
- if not hasattr(instance, '_summary') and instance._content is not None:
- content = instance._content
- begin_summary = -1
- end_summary = -1
- if instance.settings['SUMMARY_BEGIN_MARKER']:
- begin_summary = content.find(instance.settings['SUMMARY_BEGIN_MARKER'])
- if instance.settings['SUMMARY_END_MARKER']:
- end_summary = content.find(instance.settings['SUMMARY_END_MARKER'])
- if begin_summary != -1 or end_summary != -1:
- # the beginning position has to take into account the length
- # of the marker
- begin_summary = (begin_summary +
- len(instance.settings['SUMMARY_BEGIN_MARKER'])
- if begin_summary != -1 else 0)
- end_summary = end_summary if end_summary != -1 else None
- instance._summary = content[begin_summary:end_summary]
-
-def register():
- signals.initialized.connect(initialized)
- signals.content_object_init.connect(content_object_init)
diff --git a/pelican/tests/test_plugins.py b/pelican/tests/test_plugins.py
deleted file mode 100644
index 73a0fb7a..00000000
--- a/pelican/tests/test_plugins.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# -*- coding: utf-8 -*-
-'''Core plugins unit tests'''
-
-import os
-import tempfile
-
-from pelican.contents import Page
-from pelican.plugins import gzip_cache
-
-from pelican.tests.test_contents import TEST_CONTENT, TEST_SUMMARY
-from pelican.tests.support import unittest, temporary_folder
-
-
-class TestGzipCache(unittest.TestCase):
-
- def test_should_compress(self):
- # Some filetypes should compress and others shouldn't.
- self.assertTrue(gzip_cache.should_compress('foo.html'))
- self.assertTrue(gzip_cache.should_compress('bar.css'))
- self.assertTrue(gzip_cache.should_compress('baz.js'))
- self.assertTrue(gzip_cache.should_compress('foo.txt'))
-
- self.assertFalse(gzip_cache.should_compress('foo.gz'))
- self.assertFalse(gzip_cache.should_compress('bar.png'))
- self.assertFalse(gzip_cache.should_compress('baz.mp3'))
- self.assertFalse(gzip_cache.should_compress('foo.mov'))
-
- def test_creates_gzip_file(self):
- # A file matching the input filename with a .gz extension is created.
-
- # The plugin walks over the output content after the finalized signal
- # so it is safe to assume that the file exists (otherwise walk would
- # not report it). Therefore, create a dummy file to use.
- with temporary_folder() as tempdir:
- _, a_html_filename = tempfile.mkstemp(suffix='.html', dir=tempdir)
- gzip_cache.create_gzip_file(a_html_filename)
- self.assertTrue(os.path.exists(a_html_filename + '.gz'))
-
-
-class TestSummary(unittest.TestCase):
- def setUp(self):
- super(TestSummary, self).setUp()
-
- from pelican.plugins import summary
-
- summary.register()
- summary.initialized(None)
- self.page_kwargs = {
- 'content': TEST_CONTENT,
- 'context': {
- 'localsiteurl': '',
- },
- 'metadata': {
- 'summary': TEST_SUMMARY,
- 'title': 'foo bar',
- 'author': 'Blogger',
- },
- }
-
- def _copy_page_kwargs(self):
- # make a deep copy of page_kwargs
- page_kwargs = dict([(key, self.page_kwargs[key]) for key in
- self.page_kwargs])
- for key in page_kwargs:
- if not isinstance(page_kwargs[key], dict):
- break
- page_kwargs[key] = dict([(subkey, page_kwargs[key][subkey])
- for subkey in page_kwargs[key]])
-
- return page_kwargs
-
- def test_end_summary(self):
- page_kwargs = self._copy_page_kwargs()
- del page_kwargs['metadata']['summary']
- page_kwargs['content'] = (
- TEST_SUMMARY + '' + TEST_CONTENT)
- page = Page(**page_kwargs)
- # test both the summary and the marker removal
- self.assertEqual(page.summary, TEST_SUMMARY)
- self.assertEqual(page.content, TEST_SUMMARY + TEST_CONTENT)
-
- def test_begin_summary(self):
- page_kwargs = self._copy_page_kwargs()
- del page_kwargs['metadata']['summary']
- page_kwargs['content'] = (
- 'FOOBAR' + TEST_CONTENT)
- page = Page(**page_kwargs)
- # test both the summary and the marker removal
- self.assertEqual(page.summary, TEST_CONTENT)
- self.assertEqual(page.content, 'FOOBAR' + TEST_CONTENT)
-
- def test_begin_end_summary(self):
- page_kwargs = self._copy_page_kwargs()
- del page_kwargs['metadata']['summary']
- page_kwargs['content'] = (
- 'FOOBAR' + TEST_SUMMARY +
- '' + TEST_CONTENT)
- page = Page(**page_kwargs)
- # test both the summary and the marker removal
- self.assertEqual(page.summary, TEST_SUMMARY)
- self.assertEqual(page.content, 'FOOBAR' + TEST_SUMMARY + TEST_CONTENT)
diff --git a/pelican/tests/test_webassets.py b/pelican/tests/test_webassets.py
deleted file mode 100644
index fe5d6309..00000000
--- a/pelican/tests/test_webassets.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# -*- coding: utf-8 -*-
-# from __future__ import unicode_literals
-
-import hashlib
-import locale
-import os
-from codecs import open
-from tempfile import mkdtemp
-from shutil import rmtree
-
-from pelican import Pelican
-from pelican.settings import read_settings
-from .support import unittest, skipIfNoExecutable, module_exists
-
-CUR_DIR = os.path.dirname(__file__)
-THEME_DIR = os.path.join(CUR_DIR, 'themes', 'assets')
-CSS_REF = open(os.path.join(THEME_DIR, 'static', 'css',
- 'style.min.css')).read()
-CSS_HASH = hashlib.md5(CSS_REF).hexdigest()[0:8]
-
-
-@unittest.skipUnless(module_exists('webassets'), "webassets isn't installed")
-@skipIfNoExecutable(['scss', '-v'])
-@skipIfNoExecutable(['cssmin', '--version'])
-class TestWebAssets(unittest.TestCase):
- """Base class for testing webassets."""
-
- def setUp(self, override=None):
- self.temp_path = mkdtemp(prefix='pelicantests.')
- settings = {
- 'PATH': os.path.join(CUR_DIR, 'content', 'TestCategory'),
- 'OUTPUT_PATH': self.temp_path,
- 'PLUGINS': ['pelican.plugins.assets', ],
- 'THEME': THEME_DIR,
- 'LOCALE': locale.normalize('en_US'),
- }
- if override:
- settings.update(override)
-
- self.settings = read_settings(override=settings)
- pelican = Pelican(settings=self.settings)
- pelican.run()
-
- def tearDown(self):
- rmtree(self.temp_path)
-
- def check_link_tag(self, css_file, html_file):
- """Check the presence of `css_file` in `html_file`."""
-
- link_tag = (''
- .format(css_file=css_file))
- html = open(html_file).read()
- self.assertRegexpMatches(html, link_tag)
-
-
-class TestWebAssetsRelativeURLS(TestWebAssets):
- """Test pelican with relative urls."""
-
- def setUp(self):
- TestWebAssets.setUp(self, override={'RELATIVE_URLS': True})
-
- def test_jinja2_ext(self):
- # Test that the Jinja2 extension was correctly added.
-
- from webassets.ext.jinja2 import AssetsExtension
- self.assertIn(AssetsExtension, self.settings['JINJA_EXTENSIONS'])
-
- def test_compilation(self):
- # Compare the compiled css with the reference.
-
- gen_file = os.path.join(self.temp_path, 'theme', 'gen',
- 'style.{0}.min.css'.format(CSS_HASH))
- self.assertTrue(os.path.isfile(gen_file))
-
- css_new = open(gen_file).read()
- self.assertEqual(css_new, CSS_REF)
-
- def test_template(self):
- # Look in the output files for the link tag.
-
- css_file = './theme/gen/style.{0}.min.css'.format(CSS_HASH)
- html_files = ['index.html', 'archives.html',
- 'this-is-an-article-with-category.html']
- for f in html_files:
- self.check_link_tag(css_file, os.path.join(self.temp_path, f))
-
- self.check_link_tag(
- '../theme/gen/style.{0}.min.css'.format(CSS_HASH),
- os.path.join(self.temp_path, 'category/yeah.html'))
-
-
-class TestWebAssetsAbsoluteURLS(TestWebAssets):
- """Test pelican with absolute urls."""
-
- def setUp(self):
- TestWebAssets.setUp(self, override={'SITEURL': 'http://localhost'})
-
- def test_absolute_url(self):
- # Look in the output files for the link tag with absolute url.
-
- css_file = ('http://localhost/theme/gen/style.{0}.min.css'
- .format(CSS_HASH))
- html_files = ['index.html', 'archives.html',
- 'this-is-an-article-with-category.html']
- for f in html_files:
- self.check_link_tag(css_file, os.path.join(self.temp_path, f))
diff --git a/pelican/tests/themes/assets/static/css/style.min.css b/pelican/tests/themes/assets/static/css/style.min.css
deleted file mode 100644
index daf9c3cb..00000000
--- a/pelican/tests/themes/assets/static/css/style.min.css
+++ /dev/null
@@ -1 +0,0 @@
-body{font:14px/1.5 "Droid Sans",sans-serif;background-color:#e4e4e4;color:#242424}a{color:red}a:hover{color:orange}
\ No newline at end of file
diff --git a/pelican/tests/themes/assets/static/css/style.scss b/pelican/tests/themes/assets/static/css/style.scss
deleted file mode 100644
index 10cd05be..00000000
--- a/pelican/tests/themes/assets/static/css/style.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-/* -*- scss-compile-at-save: nil -*- */
-
-$baseFontFamily : "Droid Sans", sans-serif;
-$textColor : #242424;
-$bodyBackground : #e4e4e4;
-
-body {
- font: 14px/1.5 $baseFontFamily;
- background-color: $bodyBackground;
- color: $textColor;
-}
-
-a {
- color: red;
-
- &:hover {
- color: orange;
- }
-}
diff --git a/pelican/tests/themes/assets/templates/base.html b/pelican/tests/themes/assets/templates/base.html
deleted file mode 100644
index 05a32d06..00000000
--- a/pelican/tests/themes/assets/templates/base.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends "!simple/base.html" %}
-
-{% block head %}
- {% assets filters="scss,cssmin", output="gen/style.%(version)s.min.css", "css/style.scss" %}
-
- {% endassets %}
-{% endblock %}
diff --git a/setup.py b/setup.py
index b2bc2a60..8f65f82e 100755
--- a/setup.py
+++ b/setup.py
@@ -32,7 +32,7 @@ setup(
description="A tool to generate a static blog from reStructuredText or "
"Markdown input files.",
long_description=README + '\n' + CHANGELOG,
- packages=['pelican', 'pelican.tools', 'pelican.plugins'],
+ packages=['pelican', 'pelican.tools'],
include_package_data=True,
install_requires=requires,
entry_points=entry_points,