diff --git a/.travis.yml b/.travis.yml
index ea134da4..bb9a22e4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,13 +2,18 @@ language: python
python:
- "2.6"
- "2.7"
+before_install:
+ - sudo apt-get update -qq
+ - sudo apt-get install -qq ruby-sass
install:
- pip install nose unittest2 mock --use-mirrors
- pip install . --use-mirrors
- pip install Markdown
+ - pip install webassets
+ - pip install cssmin
script: nosetests -s tests
notifications:
irc:
- channels:
+ channels:
- "irc.freenode.org#pelican"
on_success: change
diff --git a/README.rst b/README.rst
index 018f73ba..b2648bf1 100644
--- a/README.rst
+++ b/README.rst
@@ -27,7 +27,7 @@ Pelican currently supports:
* Publication of articles in multiple languages
* Atom/RSS feeds
* Code syntax highlighting
-* Compilation of `LESS CSS`_ (optional)
+* Asset management with `webassets`_ (optional)
* Import from WordPress, Dotclear, or RSS feeds
* Integration with external tools: Twitter, Google Analytics, etc. (optional)
@@ -62,9 +62,9 @@ client handy, use the webchat_ for quick feedback.
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
.. _Markdown: http://daringfireball.net/projects/markdown/
.. _Jinja2: http://jinja.pocoo.org/
-.. _`LESS CSS`: http://lesscss.org/
.. _`Pelican documentation`: http://docs.getpelican.com/latest/
.. _`Pelican's internals`: http://docs.getpelican.com/en/latest/internals.html
.. _`#pelican on Freenode`: irc://irc.freenode.net/pelican
.. _webchat: http://webchat.freenode.net/?channels=pelican&uio=d4
.. _contribute: http://docs.getpelican.com/en/latest/contribute.html
+.. _webassets: https://github.com/miracle2k/webassets
diff --git a/docs/index.rst b/docs/index.rst
index 3fc1cf9f..fd99b449 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -23,7 +23,7 @@ Pelican currently supports:
* Publication of articles in multiple languages
* Atom/RSS feeds
* Code syntax highlighting
-* Compilation of `LESS CSS`_ (optional)
+* Asset management with `webassets`_ (optional)
* Import from WordPress, Dotclear, or RSS feeds
* Integration with external tools: Twitter, Google Analytics, etc. (optional)
@@ -75,8 +75,8 @@ A French version of the documentation is available at :doc:`fr/index`.
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
.. _Markdown: http://daringfireball.net/projects/markdown/
.. _Jinja2: http://jinja.pocoo.org/
-.. _`LESS CSS`: http://lesscss.org/
.. _`Pelican documentation`: http://docs.getpelican.com/latest/
.. _`Pelican's internals`: http://docs.getpelican.com/en/latest/internals.html
.. _`#pelican on Freenode`: irc://irc.freenode.net/pelican
.. _webchat: http://webchat.freenode.net/?channels=pelican&uio=d4
+.. _webassets: https://github.com/miracle2k/webassets
diff --git a/docs/plugins.rst b/docs/plugins.rst
index dc9359fe..f871a88c 100644
--- a/docs/plugins.rst
+++ b/docs/plugins.rst
@@ -59,9 +59,10 @@ Signal Arguments Description
============================= ============================ ===========================================================================
initialized pelican object
finalized pelican object invoked after all the generators are executed and just before pelican exits
- usefull for custom post processing actions, such as:
+ usefull for custom post processing actions, such as:
- minifying js/css assets.
- notify/ping search engines with an updated sitemap.
+generator_init generator invoked in the Generator.__init__
article_generate_context article_generator, metadata
article_generate_preread article_generator invoked before a article is read in ArticlesGenerator.generate_context;
use if code needs to do something before every article is parsed
@@ -77,23 +78,23 @@ pages_generator_init pages_generator invoked in the P
The list is currently small, don't hesitate to add signals and make a pull
request if you need them!
-.. note::
-
- The signal ``content_object_init`` can send different type of object as
+.. note::
+
+ The signal ``content_object_init`` can send different type of object as
argument. If you want to register only one type of object then you will
need to specify the sender when you are connecting to the signal.
-
+
::
-
+
from pelican import signals
from pelican import contents
-
+
def test(sender, instance):
print "%s : %s content initialized !!" % (sender, instance)
-
+
def register():
signals.content_object_init.connect(test, sender=contents.Article)
-
+
List of plugins
@@ -101,6 +102,7 @@ List of plugins
The following plugins are currently included with Pelican under ``pelican.plugins``:
+* `Asset management`_
* `GitHub activity`_
* `Global license`_
* `Gravatar`_
@@ -116,6 +118,79 @@ Ideas for plugins that haven't been written yet:
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`, `yuicompressor`, ...)
+* CSS compiler (`less`, `sass`, ...)
+* JS minifier (`uglifyjs`, `yuicompressor`, `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 using 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 }}`` to
+use in the templates is configured to be relative to the ``theme/`` url.
+Hence, it must be used with the ``{{ SITEURL }}`` variable which allows to
+have relative urls. 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:
+
+.. 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. However, this also means that
+the LESS and SASS files are not compiled. This should be fixed in a future
+version of `webassets` (cf. the related `bug report
+`_).
+
+.. _webassets: https://github.com/miracle2k/webassets
+.. _webassets documentation: http://webassets.readthedocs.org/en/latest/builtin_filters.html
+
+
GitHub activity
---------------
diff --git a/docs/settings.rst b/docs/settings.rst
index b278b17d..ba9a7a69 100644
--- a/docs/settings.rst
+++ b/docs/settings.rst
@@ -105,9 +105,6 @@ Setting name (default value) What doe
incorporated into the generated HTML via the `Typogrify
`_
library, which can be installed via: ``pip install typogrify``
-`LESS_GENERATOR` (``FALSE``) Set to True or complete path to `lessc` (if not
- found in system PATH) to enable compiling less
- css files. Requires installation of `less css`_.
`DIRECT_TEMPLATES` (``('index', 'tags', 'categories', 'archives')``) List of templates that are used directly to render
content. Typically direct templates are used to generate
index pages for collections of content e.g. tags and
@@ -128,8 +125,6 @@ Setting name (default value) What doe
.. [#] Default is the system locale.
-.. _less css: http://lesscss.org/
-
URL settings
------------
@@ -436,7 +431,6 @@ Setting name (default value) What does it do?
value is `static`, but if your theme has
other static paths, you can put them here.
`CSS_FILE` (``'main.css'``) Specify the CSS file you want to load.
-`WEBASSETS` (``False``) Asset management with `webassets` (see below)
================================================ =====================================================
@@ -497,75 +491,6 @@ adding the following to your configuration::
CSS_FILE = "wide.css"
-Asset management
-----------------
-
-The `WEBASSETS` setting 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`, `yuicompressor`, ...)
-* CSS compiler (`less`, `sass`, ...)
-* JS minifier (`uglifyjs`, `yuicompressor`, `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 using 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. 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:
-
-.. 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. However, this also means that
-the LESS and SASS files are not compiled. This should be fixed in a future
-version of `webassets` (cf. the related `bug report
-`_).
-
-.. _webassets: https://github.com/miracle2k/webassets
-.. _webassets documentation: http://webassets.readthedocs.org/en/latest/builtin_filters.html
-
Example settings
================
diff --git a/pelican/__init__.py b/pelican/__init__.py
index 804fe5b4..c0f33687 100644
--- a/pelican/__init__.py
+++ b/pelican/__init__.py
@@ -9,8 +9,7 @@ from pelican import signals
from pelican.generators import (ArticlesGenerator, PagesGenerator,
StaticGenerator, PdfGenerator,
- LessCSSGenerator, SourceFileGenerator,
- TemplatePagesGenerator)
+ SourceFileGenerator, TemplatePagesGenerator)
from pelican.log import init
from pelican.settings import read_settings
from pelican.utils import (clean_output_dir, files_changed, file_changed,
@@ -159,11 +158,6 @@ class Pelican(object):
writer = self.get_writer()
- # pass the assets environment to the generators
- if self.settings['WEBASSETS']:
- generators[1].env.assets_environment = generators[0].assets_env
- generators[2].env.assets_environment = generators[0].assets_env
-
for p in generators:
if hasattr(p, 'generate_output'):
p.generate_output(writer)
@@ -177,8 +171,6 @@ class Pelican(object):
generators.append(TemplatePagesGenerator)
if self.settings['PDF_GENERATOR']:
generators.append(PdfGenerator)
- if self.settings['LESS_GENERATOR']: # can be True or PATH to lessc
- generators.append(LessCSSGenerator)
if self.settings['OUTPUT_SOURCES']:
generators.append(SourceFileGenerator)
diff --git a/pelican/generators.py b/pelican/generators.py
index e0aaa130..b1d9ec12 100644
--- a/pelican/generators.py
+++ b/pelican/generators.py
@@ -62,6 +62,8 @@ class Generator(object):
custom_filters = self.settings.get('JINJA_FILTERS', {})
self.env.filters.update(custom_filters)
+ signals.generator_init.send(self)
+
def get_template(self, name):
"""Return the template by name.
Use self.theme to get the templates to use, and return a list of
@@ -477,37 +479,6 @@ class StaticGenerator(Generator):
copy(path, source, os.path.join(output_path, destination),
final_path, overwrite=True)
- def generate_context(self):
-
- if self.settings['WEBASSETS']:
- from webassets import Environment as AssetsEnvironment
-
- # Define the assets environment that will be passed to the
- # generators. The StaticGenerator must then be run first to have
- # the assets in the output_path before generating the templates.
-
- # Let ASSET_URL honor Pelican's RELATIVE_URLS setting.
- # Hint for templates:
- # Current version of webassets seem to remove any relative
- # paths at the beginning of the URL. So, if RELATIVE_URLS
- # is on, ASSET_URL will start with 'theme/', regardless if we
- # set assets_url here to './theme/' or to 'theme/'.
- # XXX However, this breaks the ASSET_URL if user navigates to
- # a sub-URL, e.g. if he clicks on a category. To workaround this
- # issue, I use
- #
- # instead of
- #
- if self.settings.get('RELATIVE_URLS'):
- assets_url = './theme/'
- else:
- assets_url = self.settings['SITEURL'] + '/theme/'
- assets_src = os.path.join(self.output_path, 'theme')
- self.assets_env = AssetsEnvironment(assets_src, assets_url)
-
- if logging.getLevelName(logger.getEffectiveLevel()) == "DEBUG":
- self.assets_env.debug = True
-
def generate_output(self, writer):
self._copy_paths(self.settings['STATIC_PATHS'], self.path,
@@ -583,49 +554,3 @@ class SourceFileGenerator(Generator):
logger.info(u' Generating source files...')
for object in chain(self.context['articles'], self.context['pages']):
self._create_source(object, self.output_path)
-
-class LessCSSGenerator(Generator):
- """Compile less css files."""
-
- def _compile(self, less_file, source_dir, dest_dir):
- base = os.path.relpath(less_file, source_dir)
- target = os.path.splitext(
- os.path.join(dest_dir, base))[0] + '.css'
- target_dir = os.path.dirname(target)
-
- if not os.path.exists(target_dir):
- try:
- os.makedirs(target_dir)
- except OSError:
- logger.error("Couldn't create the less css output folder in " +
- target_dir)
-
- subprocess.call([self._lessc, less_file, target])
- logger.info(u' [ok] compiled %s' % base)
-
- def generate_output(self, writer=None):
- logger.info(u' Compiling less css')
-
- # store out compiler here, so it won't be evaulted on each run of
- # _compile
- lg = self.settings['LESS_GENERATOR']
- self._lessc = lg if isinstance(lg, basestring) else 'lessc'
-
- # walk static paths
- for static_path in self.settings['STATIC_PATHS']:
- for f in self.get_files(
- os.path.join(self.path, static_path),
- extensions=['less']):
-
- self._compile(f, self.path, self.output_path)
-
- # walk theme static paths
- theme_output_path = os.path.join(self.output_path, 'theme')
-
- for static_path in self.settings['THEME_STATIC_PATHS']:
- theme_static_path = os.path.join(self.theme, static_path)
- for f in self.get_files(
- theme_static_path,
- extensions=['less']):
-
- self._compile(f, theme_static_path, theme_output_path)
diff --git a/pelican/plugins/assets.py b/pelican/plugins/assets.py
new file mode 100644
index 00000000..b5d1cf76
--- /dev/null
+++ b/pelican/plugins/assets.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+"""
+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)
+
+ 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/settings.py b/pelican/settings.py
index d1532bc7..49879f84 100644
--- a/pelican/settings.py
+++ b/pelican/settings.py
@@ -75,9 +75,7 @@ _DEFAULT_CONFIG = {'PATH': '.',
'DEFAULT_STATUS': 'published',
'ARTICLE_PERMALINK_STRUCTURE': '',
'TYPOGRIFY': False,
- 'LESS_GENERATOR': False,
'SUMMARY_MAX_LENGTH': 50,
- 'WEBASSETS': False,
'PLUGINS': [],
'MARKDOWN_EXTENSIONS': ['toc', ],
'TEMPLATE_PAGES': {}
@@ -133,7 +131,7 @@ def configure_settings(settings):
"""
if not 'PATH' in settings or not os.path.isdir(settings['PATH']):
raise Exception('You need to specify a path containing the content'
- ' (see pelican --help for more information)')
+ ' (see pelican --help for more information)')
# find the theme in pelican.theme if the given one does not exists
if not os.path.isdir(settings['THEME']):
@@ -143,7 +141,7 @@ def configure_settings(settings):
settings['THEME'] = theme_path
else:
raise Exception("Impossible to find the theme %s"
- % settings['THEME'])
+ % settings['THEME'])
# if locales is not a list, make it one
locales = settings['LOCALE']
@@ -197,13 +195,9 @@ def configure_settings(settings):
"http://docs.notmyidea.org/alexis/pelican/settings.html#timezone "
"for more information")
- if 'WEBASSETS' in settings and settings['WEBASSETS'] is not False:
- try:
- from webassets.ext.jinja2 import AssetsExtension
- settings['JINJA_EXTENSIONS'].append(AssetsExtension)
- except ImportError:
- logger.warn("You must install the webassets module to use WEBASSETS.")
- settings['WEBASSETS'] = False
+ if 'LESS_GENERATOR' in settings:
+ logger.warn("The LESS_GENERATOR setting has been removed in favor "
+ "of the Webassets plugin")
if 'OUTPUT_SOURCES_EXTENSION' in settings:
if not isinstance(settings['OUTPUT_SOURCES_EXTENSION'], str):
diff --git a/pelican/signals.py b/pelican/signals.py
index 241c2da2..d592599a 100644
--- a/pelican/signals.py
+++ b/pelican/signals.py
@@ -3,6 +3,7 @@ from blinker import signal
initialized = signal('pelican_initialized')
finalized = signal('pelican_finalized')
article_generate_preread = signal('article_generate_preread')
+generator_init = signal('generator_init')
article_generate_context = signal('article_generate_context')
article_generator_init = signal('article_generator_init')
article_generator_finalized = signal('article_generate_finalized')
diff --git a/tests/support.py b/tests/support.py
index 13bbfb15..52a410ff 100644
--- a/tests/support.py
+++ b/tests/support.py
@@ -3,11 +3,12 @@ __all__ = [
'unittest',
]
-import os
-import subprocess
-import re
-import sys
import cStringIO
+import importlib
+import os
+import re
+import subprocess
+import sys
from functools import wraps
from contextlib import contextmanager
@@ -138,3 +139,14 @@ def skipIfNoExecutable(executable):
return unittest.skip('{0} executable not found'.format(executable))
return lambda func: func
+
+
+def module_exists(module_name):
+ """Test if a module is importable."""
+
+ try:
+ importlib.import_module(module_name)
+ except ImportError:
+ return False
+ else:
+ return True
diff --git a/tests/test_generators.py b/tests/test_generators.py
index a4c047aa..ba7ff240 100644
--- a/tests/test_generators.py
+++ b/tests/test_generators.py
@@ -2,15 +2,16 @@
from mock import MagicMock
import os
-import re
+
+from codecs import open
from tempfile import mkdtemp
from shutil import rmtree
-from pelican.generators import ArticlesGenerator, LessCSSGenerator, \
- PagesGenerator, TemplatePagesGenerator
+from pelican.generators import ArticlesGenerator, PagesGenerator, \
+ TemplatePagesGenerator
from pelican.writers import Writer
from pelican.settings import _DEFAULT_CONFIG
-from .support import unittest, skipIfNoExecutable
+from .support import unittest
CUR_DIR = os.path.dirname(__file__)
@@ -238,55 +239,3 @@ class TestTemplatePagesGenerator(unittest.TestCase):
# output content is correct
with open(output_filename, 'r') as output_file:
self.assertEquals(output_file.read(), 'foo: bar')
-
-
-class TestLessCSSGenerator(unittest.TestCase):
-
- LESS_CONTENT = """
- @color: #4D926F;
-
- #header {
- color: @color;
- }
- h2 {
- color: @color;
- }
- """
-
- def setUp(self):
- self.temp_content = mkdtemp()
- self.temp_output = mkdtemp()
-
- def tearDown(self):
- rmtree(self.temp_content)
- rmtree(self.temp_output)
-
- @skipIfNoExecutable('lessc')
- def test_less_compiler(self):
-
- settings = _DEFAULT_CONFIG.copy()
- settings['STATIC_PATHS'] = ['static']
- settings['LESS_GENERATOR'] = True
-
- generator = LessCSSGenerator(None, settings, self.temp_content,
- _DEFAULT_CONFIG['THEME'], self.temp_output, None)
-
- # create a dummy less file
- less_dir = os.path.join(self.temp_content, 'static', 'css')
- less_filename = os.path.join(less_dir, 'test.less')
-
- less_output = os.path.join(self.temp_output, 'static', 'css',
- 'test.css')
-
- os.makedirs(less_dir)
- with open(less_filename, 'w') as less_file:
- less_file.write(self.LESS_CONTENT)
-
- generator.generate_output()
-
- # we have the file ?
- self.assertTrue(os.path.exists(less_output))
-
- # was it compiled ?
- self.assertIsNotNone(re.search(r'^\s+color:\s*#4D926F;$',
- open(less_output).read(), re.MULTILINE | re.IGNORECASE))
diff --git a/tests/test_webassets.py b/tests/test_webassets.py
new file mode 100644
index 00000000..52a7fa17
--- /dev/null
+++ b/tests/test_webassets.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+
+import hashlib
+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()
+ settings = {
+ 'PATH': os.path.join(CUR_DIR, 'content', 'TestCategory'),
+ 'OUTPUT_PATH': self.temp_path,
+ 'PLUGINS': ['pelican.plugins.assets', ],
+ 'THEME': THEME_DIR,
+ }
+ 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 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/misc.html'))
+
+
+class TestWebAssetsAbsoluteURLS(TestWebAssets):
+ """Test pelican with absolute urls."""
+
+ def setUp(self):
+ TestWebAssets.setUp(self, override={'RELATIVE_URLS': False,
+ '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/tests/themes/assets/static/css/style.min.css b/tests/themes/assets/static/css/style.min.css
new file mode 100644
index 00000000..daf9c3cb
--- /dev/null
+++ b/tests/themes/assets/static/css/style.min.css
@@ -0,0 +1 @@
+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/tests/themes/assets/static/css/style.scss b/tests/themes/assets/static/css/style.scss
new file mode 100644
index 00000000..10cd05be
--- /dev/null
+++ b/tests/themes/assets/static/css/style.scss
@@ -0,0 +1,19 @@
+/* -*- 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/tests/themes/assets/templates/base.html b/tests/themes/assets/templates/base.html
new file mode 100644
index 00000000..05a32d06
--- /dev/null
+++ b/tests/themes/assets/templates/base.html
@@ -0,0 +1,7 @@
+{% extends "!simple/base.html" %}
+
+{% block head %}
+ {% assets filters="scss,cssmin", output="gen/style.%(version)s.min.css", "css/style.scss" %}
+
+ {% endassets %}
+{% endblock %}