diff --git a/.gitignore b/.gitignore index 79b4d4a..f24ecd0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ dist MANIFEST *.pyc *.egg-info -tests/media/ +.tox/ +*.egg +docs/_build/ diff --git a/AUTHORS b/AUTHORS index c79c70f..e6a35da 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,18 +1,20 @@ -Christian Metts +Christian Metts +Carl Meyer +Jannis Leidel Django Compressor's filters started life as the filters from Andreas Pelme's django-compress. +Contributors: + Aaron Godfrey Atamert Ölçgen Ben Spaulding Benjamin Wohlwend Brad Whittington -Carl Meyer Chris Adams David Ziegler Gert Van Gool -Jannis Leidel Justin Lilly Maciek Szczesniak Mehmet S. Catalbas diff --git a/LICENSE b/LICENSE index b73e818..c293801 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ django_compressor ----------------- -Copyright (c) 2009 Christian Metts +Copyright (c) 2009-2011 django_compressor authors (see AUTHORS file) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MANIFEST.in b/MANIFEST.in index 80b58c3..403d1c6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,5 @@ include AUTHORS include README.rst include LICENSE -recursive-include compressor/templates/compressor *.html \ No newline at end of file +recursive-include compressor/templates/compressor *.html +recursive-include compressor/tests/media *.js *.css *.png diff --git a/README.rst b/README.rst index 749e191..7958f74 100644 --- a/README.rst +++ b/README.rst @@ -1,208 +1,13 @@ Django compressor -================= +================== Compresses linked and inline javascript or CSS into a single cached file. -Syntax:: +The main website for django-compressor is +`github.com/jezdez/django_compressor`_ where you can also file tickets. - {% compress %} - - {% endcompress %} +You can also install the `in-development version`_ of django-compressor with +``pip install django_compressor==dev`` or ``easy_install django_compressor==dev``. -Examples:: - - {% compress css %} - - - - {% endcompress %} - -Which would be rendered something like:: - - - -or:: - - {% compress js %} - - - {% endcompress %} - -Which would be rendered something like:: - - - -Linked files must be on your COMPRESS_URL (which defaults to MEDIA_URL). -If DEBUG is true off-site files will throw exceptions. If DEBUG is false -they will be silently stripped. - -If COMPRESS is False (defaults to the opposite of DEBUG) the compress tag -simply returns exactly what it was given, to ease development. - - -CSS Notes: -********** - -All relative url() bits specified in linked CSS files are automatically -converted to absolute URLs while being processed. Any local absolute URLs (those -starting with a '/') are left alone. - -Stylesheets that are @import'd are not compressed into the main file. They are -left alone. - -If the media attribute is set on \ No newline at end of file + diff --git a/compressor/templatetags/compress.py b/compressor/templatetags/compress.py index 534a462..83c8f26 100644 --- a/compressor/templatetags/compress.py +++ b/compressor/templatetags/compress.py @@ -1,8 +1,10 @@ import time from django import template -from django.core.cache import cache -from compressor import CssCompressor, JsCompressor + +from compressor.css import CssCompressor +from compressor.js import JsCompressor +from compressor.cache import cache from compressor.conf import settings from compressor.utils import make_offline_cache_key diff --git a/tests/__init__.py b/compressor/tests/__init__.py similarity index 100% rename from tests/__init__.py rename to compressor/tests/__init__.py diff --git a/tests/media/css/datauri.css b/compressor/tests/media/css/datauri.css similarity index 100% rename from tests/media/css/datauri.css rename to compressor/tests/media/css/datauri.css diff --git a/tests/media/css/nonasc.css b/compressor/tests/media/css/nonasc.css similarity index 100% rename from tests/media/css/nonasc.css rename to compressor/tests/media/css/nonasc.css diff --git a/tests/media/css/one.css b/compressor/tests/media/css/one.css similarity index 100% rename from tests/media/css/one.css rename to compressor/tests/media/css/one.css diff --git a/tests/media/css/two.css b/compressor/tests/media/css/two.css similarity index 100% rename from tests/media/css/two.css rename to compressor/tests/media/css/two.css diff --git a/tests/media/css/url/2/url2.css b/compressor/tests/media/css/url/2/url2.css similarity index 100% rename from tests/media/css/url/2/url2.css rename to compressor/tests/media/css/url/2/url2.css diff --git a/tests/media/css/url/nonasc.css b/compressor/tests/media/css/url/nonasc.css similarity index 100% rename from tests/media/css/url/nonasc.css rename to compressor/tests/media/css/url/nonasc.css diff --git a/tests/media/css/url/test.css b/compressor/tests/media/css/url/test.css similarity index 100% rename from tests/media/css/url/test.css rename to compressor/tests/media/css/url/test.css diff --git a/tests/media/css/url/url1.css b/compressor/tests/media/css/url/url1.css similarity index 100% rename from tests/media/css/url/url1.css rename to compressor/tests/media/css/url/url1.css diff --git a/tests/media/custom/js/3f33b9146e12.js b/compressor/tests/media/custom/js/3f33b9146e12.js similarity index 100% rename from tests/media/custom/js/3f33b9146e12.js rename to compressor/tests/media/custom/js/3f33b9146e12.js diff --git a/tests/media/custom/nested/js/3f33b9146e12.js b/compressor/tests/media/custom/nested/js/3f33b9146e12.js similarity index 100% rename from tests/media/custom/nested/js/3f33b9146e12.js rename to compressor/tests/media/custom/nested/js/3f33b9146e12.js diff --git a/tests/media/img/add.png b/compressor/tests/media/img/add.png similarity index 100% rename from tests/media/img/add.png rename to compressor/tests/media/img/add.png diff --git a/tests/media/img/python.png b/compressor/tests/media/img/python.png similarity index 100% rename from tests/media/img/python.png rename to compressor/tests/media/img/python.png diff --git a/tests/media/js/3f33b9146e12.js b/compressor/tests/media/js/3f33b9146e12.js similarity index 100% rename from tests/media/js/3f33b9146e12.js rename to compressor/tests/media/js/3f33b9146e12.js diff --git a/tests/media/js/nonasc-latin1.js b/compressor/tests/media/js/nonasc-latin1.js similarity index 100% rename from tests/media/js/nonasc-latin1.js rename to compressor/tests/media/js/nonasc-latin1.js diff --git a/tests/media/js/nonasc.js b/compressor/tests/media/js/nonasc.js similarity index 100% rename from tests/media/js/nonasc.js rename to compressor/tests/media/js/nonasc.js diff --git a/tests/media/js/one.js b/compressor/tests/media/js/one.js similarity index 100% rename from tests/media/js/one.js rename to compressor/tests/media/js/one.js diff --git a/tests/core/models.py b/compressor/tests/models.py similarity index 100% rename from tests/core/models.py rename to compressor/tests/models.py diff --git a/compressor/tests/runtests.py b/compressor/tests/runtests.py new file mode 100644 index 0000000..740f30b --- /dev/null +++ b/compressor/tests/runtests.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +import os +import sys + +from django.conf import settings + +TEST_DIR = os.path.dirname(os.path.abspath(__file__)) + +if not settings.configured: + settings.configure( + COMPRESS_CACHE_BACKEND = 'dummy://', + DATABASE_ENGINE='sqlite3', + INSTALLED_APPS=[ + 'compressor', + 'compressor.tests', + ], + MEDIA_URL = '/media/', + MEDIA_ROOT = os.path.join(TEST_DIR, 'media'), + TEMPLATE_DIRS = ( + os.path.join(TEST_DIR, 'templates'), + ), + TEST_DIR = TEST_DIR, + ) + +from django.test.simple import run_tests + + +def runtests(*test_args): + if not test_args: + test_args = ['tests'] + parent = os.path.join(TEST_DIR, "..", "..") + sys.path.insert(0, parent) + failures = run_tests(test_args, verbosity=1, interactive=True) + sys.exit(failures) + + +if __name__ == '__main__': + runtests(*sys.argv[1:]) diff --git a/compressor/tests/storage.py b/compressor/tests/storage.py new file mode 100644 index 0000000..adc5a71 --- /dev/null +++ b/compressor/tests/storage.py @@ -0,0 +1,16 @@ +import gzip +from compressor.storage import CompressorFileStorage + + +class TestStorage(CompressorFileStorage): + """ + Test compressor storage that gzips storage files + """ + def url(self, name): + return u'%s.gz' % super(TestStorage, self).url(name) + + def save(self, filename, content): + filename = super(TestStorage, self).save(filename, content) + out = gzip.open(u'%s.gz' % self.path(filename), 'wb') + out.writelines(open(self.path(filename), 'rb')) + out.close() diff --git a/tests/templates/test_compressor_offline.html b/compressor/tests/templates/test_compressor_offline.html similarity index 100% rename from tests/templates/test_compressor_offline.html rename to compressor/tests/templates/test_compressor_offline.html diff --git a/tests/core/tests.py b/compressor/tests/tests.py similarity index 94% rename from tests/core/tests.py rename to compressor/tests/tests.py index ca4a3b2..e1f7189 100644 --- a/tests/core/tests.py +++ b/compressor/tests/tests.py @@ -1,17 +1,18 @@ import os import re -import gzip from BeautifulSoup import BeautifulSoup from django.template import Template, Context, TemplateSyntaxError from django.test import TestCase from django.core.files.storage import get_storage_class from django.conf import settings as django_settings +from django.core.cache.backends import dummy -from compressor import CssCompressor, JsCompressor, storage +from compressor import storage +from compressor.css import CssCompressor +from compressor.js import JsCompressor from compressor.conf import settings -from compressor.storage import CompressorFileStorage -from compressor.utils import get_hexdigest, get_mtime +from compressor.utils import get_hashed_mtime class CompressorTestCase(TestCase): @@ -66,7 +67,7 @@ class CompressorTestCase(TestCase): self.assertEqual('f7c661b7a124', self.cssNode.hash) def test_css_return_if_on(self): - output = u'' + output = u'' self.assertEqual(output, self.cssNode.output().strip()) def test_js_split(self): @@ -110,6 +111,7 @@ class CompressorTestCase(TestCase): self.assertEqual(output, JsCompressor(self.js).output()) settings.OUTPUT_DIR = old_output_dir + class LxmlCompressorTestCase(CompressorTestCase): def test_css_split(self): @@ -130,10 +132,6 @@ class LxmlCompressorTestCase(CompressorTestCase): def tearDown(self): settings.PARSER = self.old_parser -def get_hashed_mtime(filename, length=12): - filename = os.path.realpath(filename) - mtime = str(int(get_mtime(filename))) - return get_hexdigest(mtime)[:length] class CssAbsolutizingTestCase(TestCase): def setUp(self): @@ -180,7 +178,6 @@ class CssAbsolutizingTestCase(TestCase): output = "p { background: url('%simages/image.gif?%s') }" % (settings.MEDIA_URL, get_hashed_mtime(filename)) self.assertEqual(output, filter.input(filename=filename)) - def test_css_hunks(self): hash_dict = { 'hash1': get_hashed_mtime(os.path.join(settings.MEDIA_ROOT, 'css/url/url1.css')), @@ -276,7 +273,7 @@ class TemplatetagTestCase(TestCase): {% endcompress %} """ context = { 'MEDIA_URL': settings.MEDIA_URL } - out = u'' + out = u'' self.assertEqual(out, render(template, context)) def test_nonascii_css_tag(self): @@ -286,7 +283,7 @@ class TemplatetagTestCase(TestCase): {% endcompress %} """ context = { 'MEDIA_URL': settings.MEDIA_URL } - out = '' + out = '' self.assertEqual(out, render(template, context)) def test_js_tag(self): @@ -325,23 +322,11 @@ class TemplatetagTestCase(TestCase): {% endcompress %}""" self.assertRaises(TemplateSyntaxError, render, template, {}) -class TestStorage(CompressorFileStorage): - """ - Test compressor storage that gzips storage files - """ - def url(self, name): - return u'%s.gz' % super(TestStorage, self).url(name) - - def save(self, filename, content): - filename = super(TestStorage, self).save(filename, content) - out = gzip.open(u'%s.gz' % self.path(filename), 'wb') - out.writelines(open(self.path(filename), 'rb')) - out.close() class StorageTestCase(TestCase): def setUp(self): self._storage = storage.default_storage - storage.default_storage = get_storage_class('core.tests.TestStorage')() + storage.default_storage = get_storage_class('compressor.tests.storage.TestStorage')() settings.COMPRESS = True def tearDown(self): @@ -355,7 +340,7 @@ class StorageTestCase(TestCase): {% endcompress %} """ context = { 'MEDIA_URL': settings.MEDIA_URL } - out = u'' + out = u'' self.assertEqual(out, render(template, context)) @@ -364,3 +349,10 @@ class VerboseTestCase(CompressorTestCase): def setUp(self): super(VerboseTestCase, self).setUp() setattr(settings, "COMPRESS_VERBOSE", True) + + +class CacheBackendTestCase(CompressorTestCase): + + def test_correct_backend(self): + from compressor.cache import cache + self.assertEqual(cache.__class__, dummy.CacheClass) diff --git a/compressor/utils.py b/compressor/utils.py index ab718c8..fdffddc 100644 --- a/compressor/utils.py +++ b/compressor/utils.py @@ -1,5 +1,7 @@ import os -from django.core.cache import cache +from shlex import split as cmd_split + +from compressor.cache import cache from compressor.conf import settings from compressor.exceptions import FilterError @@ -27,6 +29,11 @@ def get_mtime(filename): return mtime return os.path.getmtime(filename) +def get_hashed_mtime(filename, length=12): + filename = os.path.realpath(filename) + mtime = str(int(get_mtime(filename))) + return get_hexdigest(mtime)[:length] + def get_class(class_string, exception=FilterError): """ @@ -57,3 +64,18 @@ def get_mod_func(callback): except ValueError: return callback, '' return callback[:dot], callback[dot+1:] + + +def walk(root, topdown=True, onerror=None, followlinks=False): + """ + A version of os.walk that can follow symlinks for Python < 2.6 + """ + for dirpath, dirnames, filenames in os.walk(root, topdown, onerror): + yield (dirpath, dirnames, filenames) + if followlinks: + for d in dirnames: + p = os.path.join(dirpath, d) + if os.path.islink(p): + for link_dirpath, link_dirnames, link_filenames in walk(p): + yield (link_dirpath, link_dirnames, link_filenames) + diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..e4de9f8 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,130 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/django-compressor.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django-compressor.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/django-compressor" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/django-compressor" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/docs/_theme/compressor/static/compressor.css_t b/docs/_theme/compressor/static/compressor.css_t new file mode 100644 index 0000000..00b57e8 --- /dev/null +++ b/docs/_theme/compressor/static/compressor.css_t @@ -0,0 +1,238 @@ +/** + * Sphinx stylesheet -- default theme + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Arial, sans-serif; + font-size: 100%; + background-color: #111111; + color: #555555; + margin: 0; + padding: 0; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 300px; +} + +hr{ + border: 1px solid #B1B4B6; +} + +div.document { + background-color: #fafafa; +} + +div.body { + background-color: #ffffff; + color: #3E4349; + padding: 1em 30px 30px 30px; + font-size: 0.9em; +} + +div.footer { + color: #555; + width: 100%; + padding: 13px 0; + text-align: center; + font-size: 75%; +} + +div.footer a { + color: #444444; +} + +div.related { + background-color: #6b2a1e; + color: #ffffff; + font: 1.2em/40px "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif; +} + +span.pre { + font: 0.7em Monaco, "Courier New", Courier, mono; +} + +div.related a { + color: #fff4eb; +} + +div.related .right { + font-size: 0.9em; +} + +div.sphinxsidebar { + font-size: 0.9em; + line-height: 1.5em; + width: 300px +} + +div.sphinxsidebarwrapper{ + padding: 20px 0; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Arial, sans-serif; + color: #222222; + font-size: 1.2em; + font-weight: bold; + margin: 0; + padding: 5px 10px; + text-shadow: 1px 1px 0 white +} + +div.sphinxsidebar h3 a { + color: #444444; +} + +div.sphinxsidebar p { + color: #888888; + padding: 5px 20px; + margin: 0.5em 0px; +} + +div.sphinxsidebar p.topless { +} + +div.sphinxsidebar ul { + margin: 10px 10px 10px 20px; + padding: 0; + color: #000000; +} + +div.sphinxsidebar a { + color: #444444; +} + +div.sphinxsidebar a:hover { + color: #E32E00; +} + +div.sphinxsidebar input { + border: 1px solid #cccccc; + font-family: sans-serif; + font-size: 1.1em; + padding: 0.15em 0.3em; +} + +div.sphinxsidebar input[type=text]{ + margin-left: 20px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #005B81; + text-decoration: none; +} + +a:hover { + color: #E32E00; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Arial, sans-serif; + font-weight: normal; + color: #212224; + margin: 30px 0px 10px 0px; + padding: 5px 0 5px 0px; + text-shadow: 0px 1px 0 white; + border-bottom: 1px solid #C8D5E3; +} + +div.body h1 { margin-top: 0; font-size: 200%; } +div.body h2 { font-size: 150%; } +div.body h3 { font-size: 120%; } +div.body h4 { font-size: 110%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #c60f0f; + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + background-color: #c60f0f; + color: white; +} + +div.body p, div.body dd, div.body li { + line-height: 1.8em; +} + +div.admonition p.admonition-title + p { + display: inline; +} + +div.highlight{ + background-color: white; +} + +div.note { + background-color: #eeeeee; + border: 1px solid #cccccc; +} + +div.seealso { + background-color: #ffffcc; + border: 1px solid #ffff66; +} + +div.topic { + background-color: #fafafa; + border-width: 0; +} + +div.warning { + background-color: #ffe4e4; + border: 1px solid #ff6666; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre { + padding: 4px 6px; + background-color: #fff; + border: 1px solid #ccc; + color: #222222; + margin: 1.5em 0 1.5em 0; + border-right-color: #e3e3e3; + border-bottom-color: #e3e3e3; + line-height: 1.5em; + font-size: 1.1em; +} + +tt { + color: #222222; + padding: 1px 2px; + font-size: 1.2em; + font-family: monospace; +} + +#table-of-contents ul { + padding-left: 2em; +} diff --git a/docs/_theme/compressor/theme.conf b/docs/_theme/compressor/theme.conf new file mode 100644 index 0000000..672669a --- /dev/null +++ b/docs/_theme/compressor/theme.conf @@ -0,0 +1,3 @@ +[theme] +inherit = basic +stylesheet = compressor.css diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..2b376ca --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +# +# django-compressor documentation build configuration file, created by +# sphinx-quickstart on Fri Jan 21 11:47:42 2011. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# sys.path.insert(0, os.path.abspath('..')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +# extensions = ['sphinx.ext.autodoc', 'sphinx.ext.coverage'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.txt' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Django compressor' +copyright = u'2011, Django compressor authors' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.6' +# The full version, including alpha/beta/rc tags. +release = '0.6a8' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'murphy' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'compressor' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = ['_theme'] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'django-compressordoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'django-compressor.tex', u'Django compressor Documentation', + u'Django compressor authors', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'django-compressor', u'Django compressor Documentation', + [u'Django compressor authors'], 1) +] diff --git a/docs/index.txt b/docs/index.txt new file mode 100644 index 0000000..8be4921 --- /dev/null +++ b/docs/index.txt @@ -0,0 +1,240 @@ +Django compressor +================= + +Compresses linked and inline javascript or CSS into a single cached file. + +Syntax: + +.. code-block:: django + + {% load compress %} + {% compress %} + + {% endcompress %} + +Examples: + +.. code-block:: django + + {% load compress %} + {% compress css %} + + + + {% endcompress %} + +Which would be rendered something like: + +.. code-block:: html + + + +or: + +.. code-block:: django + + {% load compress %} + {% compress js %} + + + {% endcompress %} + +Which would be rendered something like: + +.. code-block:: html + + + +Linked files must be on your COMPRESS_URL (which defaults to MEDIA_URL). +If DEBUG is true off-site files will throw exceptions. If DEBUG is false +they will be silently stripped. + +If COMPRESS is False (defaults to the opposite of DEBUG) the compress tag +simply returns exactly what it was given, to ease development. + +.. note:: + + For production sites it is advisable to use a real cache backend such as + memcached to speed up the checks of compressed files. Make sure you set + your Django cache backend appropriately. + + +CSS Notes: +********** + +All relative ``url()`` bits specified in linked CSS files are automatically +converted to absolute URLs while being processed. Any local absolute URLs (those +starting with a ``'/'``) are left alone. + +Stylesheets that are ``@import``'d are not compressed into the main file. +They are left alone. + +If the media attribute is set on