├── .github
└── workflows
│ └── lint-and-test.yml
├── .gitignore
├── .pre-commit-config.yaml
├── LICENSE.md
├── MANIFEST.in
├── README.md
├── django_inlinecss
├── __init__.py
├── __version__.py
├── conf.py
├── css_loaders.py
├── engines.py
├── models.py
├── templatetags
│ ├── __init__.py
│ └── inlinecss.py
└── tests
│ ├── __init__.py
│ ├── static
│ ├── bar.css
│ ├── foo.css
│ └── foobar.css
│ ├── templates
│ ├── base.html
│ ├── comments_are_ignored.html
│ ├── context_vars_render_first.html
│ ├── inline_css.html
│ ├── multiple_staticfiles_css.html
│ ├── single_staticfiles_css.html
│ ├── template_inheritance.html
│ ├── template_inheritance_base.html
│ ├── unicode_context_variables.html
│ ├── variable_and_string_defined_staticfiles_css.html
│ └── variable_defined_staticfiles_css.html
│ ├── test_css_loaders.py
│ └── test_templatetags.py
├── setup.cfg
├── setup.py
└── test_settings.py
/.github/workflows/lint-and-test.yml:
--------------------------------------------------------------------------------
1 | name: Run Tests and Linter
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | - main
8 |
9 | jobs:
10 | lint-and-test:
11 | runs-on: ubuntu-latest
12 | strategy:
13 | fail-fast: false
14 | matrix:
15 | python-version: [3.8.18, 3.9.18, 3.10.13, 3.11.8]
16 | django-version: [3.2, 4.2]
17 |
18 | name: Lint and Test (Python ${{ matrix.python-version }} - Django ${{ matrix.django-version }})
19 |
20 | steps:
21 | - uses: actions/checkout@v4
22 |
23 | - name: Set up Python ${{ matrix.python-version }}
24 | uses: actions/setup-python@v5
25 | with:
26 | python-version: ${{ matrix.python-version }}
27 |
28 | - name: Install dependencies
29 | run: |
30 | pip install -q Django==${{ matrix.django-version }}
31 | pip install -e .[flake8,tests]
32 |
33 | - name: Add current directory to PYTHONPATH
34 | run: echo "PYTHONPATH=$PWD" >> $GITHUB_ENV
35 |
36 | - name: Lint with flake8
37 | run: flake8
38 |
39 | - name: Test with pytest
40 | run: pytest
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | # Byte-compiled / optimized / DLL files
4 | __pycache__/
5 | *.py[cod]
6 | *$py.class
7 |
8 | # C extensions
9 | *.so
10 |
11 | # Distribution / packaging
12 | .Python
13 | build/
14 | develop-eggs/
15 | dist/
16 | downloads/
17 | eggs/
18 | .eggs/
19 | lib/
20 | lib64/
21 | parts/
22 | sdist/
23 | var/
24 | wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | .hypothesis/
50 | .pytest_cache/
51 |
52 | # Translations
53 | *.mo
54 | *.pot
55 |
56 | # Django stuff:
57 | *.log
58 | local_settings.py
59 | db.sqlite3
60 |
61 | # Flask stuff:
62 | instance/
63 | .webassets-cache
64 |
65 | # Scrapy stuff:
66 | .scrapy
67 |
68 | # Sphinx documentation
69 | docs/_build/
70 |
71 | # PyBuilder
72 | target/
73 |
74 | # Jupyter Notebook
75 | .ipynb_checkpoints
76 |
77 | # pyenv
78 | .python-version
79 |
80 | # celery beat schedule file
81 | celerybeat-schedule
82 |
83 | # SageMath parsed files
84 | *.sage.py
85 |
86 | # Environments
87 | .env
88 | .venv
89 | env/
90 | venv/
91 | ENV/
92 | env.bak/
93 | venv.bak/
94 |
95 | # Spyder project settings
96 | .spyderproject
97 | .spyproject
98 |
99 | # Rope project settings
100 | .ropeproject
101 |
102 | # mkdocs documentation
103 | /site
104 |
105 | # mypy
106 | .mypy_cache/
107 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v4.5.0
4 | hooks:
5 | - id: trailing-whitespace
6 | args: [--markdown-linebreak-ext=md]
7 | - id: end-of-file-fixer
8 | - id: check-toml
9 | - id: check-added-large-files
10 | - id: debug-statements
11 | - repo: https://github.com/PyCQA/flake8
12 | rev: "7.0.0"
13 | hooks:
14 | - id: flake8
15 | additional_dependencies:
16 | - flake8-bugbear
17 | - flake8-isort
18 | - repo: https://github.com/psf/black
19 | rev: "24.2.0"
20 | hooks:
21 | - id: black
22 | - repo: https://github.com/pycqa/isort
23 | rev: 5.13.2
24 | hooks:
25 | - id: isort
26 | name: isort (python)
27 | - repo: https://github.com/myint/autoflake
28 | rev: v2.2.1
29 | hooks:
30 | - id: autoflake
31 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | ## django-inlinecss
2 |
3 | Copyright (c) 2012 Philip Kimmey & Thomas Yip
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
9 | ## pynliner
10 |
11 | Pynliner is included along with additional improvements to soupselect that are not
12 | broadly available (via PyPI for example).
13 |
14 | Copyright (c) 2011 Tanner Netterville
15 |
16 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
17 |
18 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
19 |
20 | The generated output of this software shall not be used in a mass marketing service.
21 |
22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include README.md
2 | recursive-include django_inlinecss *.py
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/roverdotcom/django-inlinecss)
2 |
3 | ## About
4 |
5 | Inlining CSS is necessary for email generation and sending
6 | but is currently a surprisingly large hassle.
7 |
8 | This library aims to make it a breeze in the Django
9 | template language.
10 |
11 | ## Usage
12 |
13 | #### Step 1: Dependencies
14 |
15 | - BeautifulSoup
16 | - cssutils
17 | - Python 3.8+
18 | - Django 3.2+
19 |
20 |
21 | #### Step 2: Install django_inlinecss
22 |
23 | Add ```django_inlinecss``` to your ```settings.py```:
24 |
25 | ```python
26 | INSTALLED_APPS = (
27 | 'django.contrib.auth',
28 | 'django.contrib.webdesign',
29 | 'django.contrib.contenttypes',
30 | '...',
31 | '...',
32 | '...',
33 | 'django_inlinecss')
34 | ```
35 |
36 | #### Step 3: Use the templatetag
37 |
38 | 1. Place your CSS file somewhere staticfiles can find it
39 | 2. Create your template:
40 |
41 | ```html
42 | {% load inlinecss %}
43 | {% inlinecss "css/extra-padding.css" %}
44 |
45 |
46 |
47 | Something in need of styling.
48 |
49 |
50 |
51 | {% endinlinecss %}
52 | ```
53 |
54 | #### Step 4: Prepare to be Wowed
55 |
56 | ```html
57 |
58 |
59 |
60 | Something in need of styling.
61 |
62 |
63 |
64 | ```
65 |
66 | ## Acknowledgements
67 |
68 | Thanks to Tanner Netterville for his efforts on [Pynliner](https://github.com/rennat/pynliner).
69 |
70 | Thanks to Thomas Yip for his unit tests on the `soupselect` module. These tests
71 | helped on getting the core CSS2 selectors to work.
72 |
73 | ## License
74 |
75 | MIT license. See LICENSE.md for more detail.
76 |
--------------------------------------------------------------------------------
/django_inlinecss/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roverdotcom/django-inlinecss/d69f93bbc241f372e5a27342d42948285cf1d97b/django_inlinecss/__init__.py
--------------------------------------------------------------------------------
/django_inlinecss/__version__.py:
--------------------------------------------------------------------------------
1 | VERSION = (0, 4, 0)
2 |
3 | __version__ = ".".join(map(str, VERSION))
4 |
--------------------------------------------------------------------------------
/django_inlinecss/conf.py:
--------------------------------------------------------------------------------
1 | try:
2 | import importlib
3 | except ImportError:
4 | from django.utils import importlib
5 |
6 | DEFAULT_ENGINE = "django_inlinecss.engines.PynlinerEngine"
7 | DEFAULT_CSS_LOADER = "django_inlinecss.css_loaders.StaticfilesStorageCSSLoader"
8 |
9 |
10 | def load_class_by_path(path):
11 | i = path.rfind(".")
12 | module_path, class_name = path[:i], path[i + 1 :]
13 | module = importlib.import_module(module_path)
14 | return getattr(module, class_name)
15 |
16 |
17 | def get_engine():
18 | from django.conf import settings
19 |
20 | engine_path = getattr(settings, "INLINECSS_ENGINE", DEFAULT_ENGINE)
21 | return load_class_by_path(engine_path)
22 |
23 |
24 | def get_css_loader():
25 | from django.conf import settings
26 |
27 | engine_path = getattr(settings, "INLINECSS_CSS_LOADER", DEFAULT_CSS_LOADER)
28 | return load_class_by_path(engine_path)
29 |
--------------------------------------------------------------------------------
/django_inlinecss/css_loaders.py:
--------------------------------------------------------------------------------
1 | from django.contrib.staticfiles import finders
2 | from django.contrib.staticfiles.storage import staticfiles_storage
3 |
4 |
5 | class BaseCSSLoader:
6 | def __init__(self):
7 | pass
8 |
9 | def load(self, path):
10 | """
11 | Retrieves the contents of the static asset specified
12 | :param path: path to the desired asset
13 | :return: contents of asset
14 | """
15 | raise NotImplementedError()
16 |
17 |
18 | class StaticfilesFinderCSSLoader(BaseCSSLoader):
19 | def load(self, path):
20 | """
21 | Retrieve CSS contents from the local filesystem with static finders
22 | """
23 | expanded_path = finders.find(path)
24 |
25 | if expanded_path is None:
26 | raise OSError(f"{path} does not exist")
27 |
28 | with open(expanded_path, "rb") as css_file:
29 | return css_file.read().decode("utf-8")
30 |
31 |
32 | class StaticfilesStorageCSSLoader(BaseCSSLoader):
33 | def load(self, path):
34 | """
35 | Retrieve CSS contents with staticfiles storage
36 | """
37 | return staticfiles_storage.open(path).read().decode("utf-8")
38 |
--------------------------------------------------------------------------------
/django_inlinecss/engines.py:
--------------------------------------------------------------------------------
1 | import pynliner
2 |
3 |
4 | class EngineBase:
5 | def __init__(self, html, css):
6 | self.html = html
7 | self.css = css
8 |
9 | def render(self):
10 | raise NotImplementedError()
11 |
12 |
13 | class PynlinerEngine(EngineBase):
14 | def render(self):
15 | inliner = pynliner.Pynliner().from_string(self.html)
16 | inliner = inliner.with_cssString(self.css)
17 | return inliner.run()
18 |
19 |
20 | class NullEngine(EngineBase):
21 | def render(self):
22 | return self.html
23 |
--------------------------------------------------------------------------------
/django_inlinecss/models.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roverdotcom/django-inlinecss/d69f93bbc241f372e5a27342d42948285cf1d97b/django_inlinecss/models.py
--------------------------------------------------------------------------------
/django_inlinecss/templatetags/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roverdotcom/django-inlinecss/d69f93bbc241f372e5a27342d42948285cf1d97b/django_inlinecss/templatetags/__init__.py
--------------------------------------------------------------------------------
/django_inlinecss/templatetags/inlinecss.py:
--------------------------------------------------------------------------------
1 | from django import template
2 | from django.utils.encoding import smart_str
3 |
4 | from django_inlinecss import conf
5 |
6 | register = template.Library()
7 |
8 |
9 | class InlineCssNode(template.Node):
10 | def __init__(self, nodelist, filter_expressions):
11 | self.nodelist = nodelist
12 | self.filter_expressions = filter_expressions
13 |
14 | def render(self, context):
15 | rendered_contents = self.nodelist.render(context)
16 | css = ""
17 | for expression in self.filter_expressions:
18 | path = expression.resolve(context, True)
19 | if path is not None:
20 | path = smart_str(path)
21 |
22 | css_loader = conf.get_css_loader()()
23 | css = "".join((css, css_loader.load(path)))
24 |
25 | engine = conf.get_engine()(html=rendered_contents, css=css)
26 | return engine.render()
27 |
28 |
29 | @register.tag
30 | def inlinecss(parser, token):
31 | nodelist = parser.parse(("endinlinecss",))
32 |
33 | # prevent second parsing of endinlinecss
34 | parser.delete_first_token()
35 |
36 | args = token.split_contents()[1:]
37 |
38 | return InlineCssNode(nodelist, [parser.compile_filter(arg) for arg in args])
39 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roverdotcom/django-inlinecss/d69f93bbc241f372e5a27342d42948285cf1d97b/django_inlinecss/tests/__init__.py
--------------------------------------------------------------------------------
/django_inlinecss/tests/static/bar.css:
--------------------------------------------------------------------------------
1 | div.bar {
2 | padding: 10px 15px 20px 25px;
3 | }
4 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/static/foo.css:
--------------------------------------------------------------------------------
1 | div.foo {
2 | margin: 10px 15px 20px 25px;
3 | }
4 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/static/foobar.css:
--------------------------------------------------------------------------------
1 | div.foo {
2 | margin: 10px 15px 20px 25px;
3 | }
4 | div.bar {
5 | padding: 10px 15px 20px 25px;
6 | }
7 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/templates/base.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roverdotcom/django-inlinecss/d69f93bbc241f372e5a27342d42948285cf1d97b/django_inlinecss/tests/templates/base.html
--------------------------------------------------------------------------------
/django_inlinecss/tests/templates/comments_are_ignored.html:
--------------------------------------------------------------------------------
1 | {% load inlinecss %}
2 |
3 | {% inlinecss "foobar.css" %}
4 |
5 |
6 |
7 | This is the "foo" div.
8 |
9 |
10 |
11 | This is the "bar" div.
12 |
13 |
14 |
15 | {% endinlinecss %}
16 |
17 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/templates/context_vars_render_first.html:
--------------------------------------------------------------------------------
1 | {% load inlinecss %}
2 | {% inlinecss "foobar.css" %}
3 |
4 |
5 | {{ foo_div_open_tag }}
6 | This is the "foo" div.
7 |
8 | {{ bar_div_open_tag }}
9 | This is the "bar" div.
10 |
11 |
12 |
13 | {% endinlinecss %}
14 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/templates/inline_css.html:
--------------------------------------------------------------------------------
1 | {% load inlinecss %}
2 | {% inlinecss %}
3 |
4 |
5 |
13 |
14 |
15 |
16 | This is the "foo" div.
17 |
18 |
19 | This is the "bar" div.
20 |
21 |
22 |
23 | {% endinlinecss %}
24 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/templates/multiple_staticfiles_css.html:
--------------------------------------------------------------------------------
1 | {% load inlinecss %}
2 | {% inlinecss "foo.css" "bar.css" %}
3 |
4 |
5 |
6 | This is the "foo" div.
7 |
8 |
9 | This is the "bar" div.
10 |
11 |
12 |
13 | {% endinlinecss %}
14 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/templates/single_staticfiles_css.html:
--------------------------------------------------------------------------------
1 | {% load inlinecss %}
2 | {% inlinecss "foobar.css" %}
3 |
4 |
5 |
6 | This is the "foo" div.
7 |
8 |
9 | This is the "bar" div.
10 |
11 |
12 |
13 | {% endinlinecss %}
14 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/templates/template_inheritance.html:
--------------------------------------------------------------------------------
1 | {% extends "template_inheritance_base.html" %}
2 |
3 | {% block content %}
4 |
5 | This is the "foo" div.
6 |
7 |
8 | This is the "bar" div.
9 |
10 | {% endblock %}
11 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/templates/template_inheritance_base.html:
--------------------------------------------------------------------------------
1 | {% load inlinecss %}
2 | {% inlinecss "foobar.css" %}
3 |
4 |
5 | {% block content %}
6 |
7 | {% endblock %}
8 |
9 |
10 | {% endinlinecss %}
11 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/templates/unicode_context_variables.html:
--------------------------------------------------------------------------------
1 | {% load inlinecss %}
2 | {% inlinecss "foobar.css" %}
3 |
4 |
5 |
6 | This is the "foo" div.
7 |
8 |
9 | {{ unicode_string }}
10 |
11 |
12 |
13 | {% endinlinecss %}
14 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/templates/variable_and_string_defined_staticfiles_css.html:
--------------------------------------------------------------------------------
1 | {% load inlinecss %}
2 | {% inlinecss foo_css "bar.css" %}
3 |
4 |
5 |
6 | This is the "foo" div.
7 |
8 |
9 | This is the "bar" div.
10 |
11 |
12 |
13 | {% endinlinecss %}
14 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/templates/variable_defined_staticfiles_css.html:
--------------------------------------------------------------------------------
1 | {% load inlinecss %}
2 | {% inlinecss foo_css bar_css %}
3 |
4 |
5 |
6 | This is the "foo" div.
7 |
8 |
9 | This is the "bar" div.
10 |
11 |
12 |
13 | {% endinlinecss %}
14 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/test_css_loaders.py:
--------------------------------------------------------------------------------
1 | """
2 | Test CSS loaders
3 | """
4 |
5 | from django.conf import settings
6 | from django.test import TestCase
7 | from django.test import override_settings
8 |
9 | from django_inlinecss.css_loaders import StaticfilesFinderCSSLoader
10 | from django_inlinecss.css_loaders import StaticfilesStorageCSSLoader
11 |
12 |
13 | @override_settings(STATICFILES_DIRS=[settings.STATIC_ROOT], STATIC_ROOT="")
14 | class StaticfilesFinderCSSLoaderTestCase(TestCase):
15 | def setUp(self):
16 | self.loader = StaticfilesFinderCSSLoader()
17 | super().setUp()
18 |
19 | def test_loads_existing_css_file(self):
20 | css = self.loader.load("bar.css")
21 | self.assertIn("div.bar {", css)
22 |
23 | def test_load_file_does_not_exist(self):
24 | with self.assertRaises(IOError) as e:
25 | self.loader.load("missing.css")
26 |
27 | self.assertEqual(str(e.exception), "missing.css does not exist")
28 |
29 |
30 | class StaticfilesStorageCSSLoaderTestCase(TestCase):
31 | def setUp(self):
32 | self.loader = StaticfilesStorageCSSLoader()
33 | super().setUp()
34 |
35 | def test_loads_existing_css_file(self):
36 | css = self.loader.load("bar.css")
37 | self.assertIn("div.bar {", css)
38 |
39 | def test_load_file_does_not_exist(self):
40 | with self.assertRaises(IOError) as e:
41 | self.loader.load("missing.css")
42 |
43 | self.assertEqual(e.exception.strerror, "No such file or directory")
44 |
--------------------------------------------------------------------------------
/django_inlinecss/tests/test_templatetags.py:
--------------------------------------------------------------------------------
1 | """
2 | Test the functioning of the templatetag itself.
3 |
4 | The actual CSS inlining displayed here is extremely simple:
5 | tests of the CSS selector functionality is independent.
6 | """
7 |
8 | import os
9 | from unittest.mock import patch
10 |
11 | from django.conf import settings
12 | from django.template.loader import get_template
13 | from django.test import TestCase
14 | from django.test.utils import override_settings
15 | from django.utils.safestring import mark_safe
16 |
17 |
18 | class InlinecssTests(TestCase):
19 | def setUp(self):
20 | super().setUp()
21 |
22 | def assert_foo_and_bar_rendered(self, rendered):
23 | foo_div_regex = (
24 | r''
25 | r'\s+This is the "foo" div.\s+'
26 | r"<\/div>"
27 | )
28 | self.assertRegex(rendered, foo_div_regex)
29 |
30 | bar_div_regex = (
31 | r'
'
32 | r'\s+This is the "bar" div.\s+'
33 | r"<\/div>"
34 | )
35 | self.assertRegex(rendered, bar_div_regex)
36 |
37 | def test_single_staticfiles_css(self):
38 | """
39 | Test the basic inlining case of using the staticfiles loader
40 | to load a CSS file and inline it as part of a rendering step.
41 | """
42 | template = get_template("single_staticfiles_css.html")
43 | rendered = template.render({})
44 | self.assert_foo_and_bar_rendered(rendered)
45 |
46 | def test_multiple_staticfiles_css(self):
47 | """
48 | Test the multiple inlining case of using the staticfiles loader.
49 |
50 | This tests that passing two css files works.
51 | """
52 | template = get_template("multiple_staticfiles_css.html")
53 | rendered = template.render({})
54 | self.assert_foo_and_bar_rendered(rendered)
55 |
56 | def test_variable_defined_staticfiles_css(self):
57 | """
58 | Test that the staticfiles paths passed to the templatetag
59 | may be defined as variables instead of strings.
60 | """
61 | template = get_template("variable_defined_staticfiles_css.html")
62 | context = {"foo_css": "foo.css", "bar_css": "bar.css"}
63 |
64 | rendered = template.render(context)
65 | self.assert_foo_and_bar_rendered(rendered)
66 |
67 | def test_variable_and_string_defined_staticfiles_css(self):
68 | """
69 | Test that we can mix and match variable-defined CSS files &
70 | those defined quoted in the templatetag.
71 | """
72 | template = get_template("variable_and_string_defined_staticfiles_css.html")
73 | context = {"foo_css": "foo.css"}
74 | rendered = template.render(context)
75 | self.assert_foo_and_bar_rendered(rendered)
76 |
77 | def test_inline_css(self):
78 | """
79 | Test that