Full Code of torchbox/django-libsass for AI

main 8fb6d21cf975 cached
28 files
23.7 KB
6.3k tokens
18 symbols
1 requests
Download .txt
Repository: torchbox/django-libsass
Branch: main
Commit: 8fb6d21cf975
Files: 28
Total size: 23.7 KB

Directory structure:
gitextract_dyb7hi3g/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── bug_report.md
│   └── workflows/
│       └── test.yml
├── .gitignore
├── CHANGELOG.txt
├── LICENSE
├── MANIFEST.in
├── README.rst
├── django_libsass.py
├── runtests.py
├── setup.cfg
├── setup.py
├── tests/
│   ├── __init__.py
│   ├── extra_static/
│   │   └── extra.scss
│   ├── settings.py
│   ├── static/
│   │   └── css/
│   │       ├── imported.scss
│   │       ├── index.scss
│   │       ├── raw1.css
│   │       ├── raw2.css
│   │       ├── with_extra_include.scss
│   │       ├── with_import.scss
│   │       ├── with_raw_css_import.scss
│   │       └── with_static.scss
│   ├── templates/
│   │   └── index.html
│   ├── tests/
│   │   ├── __init__.py
│   │   └── test_sass.py
│   ├── urls.py
│   └── views.py
└── tox.ini

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

Please see https://github.com/torchbox/django-libsass#reporting-bugs before reporting. Any bug reports relating to a third-party CSS framework are liable to be closed without further investigation.


================================================
FILE: .github/workflows/test.yml
================================================
name: Unit tests

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    name: Python ${{ matrix.python-version }}, django ${{ matrix.django-version }}
    runs-on: ubuntu-latest
    strategy:
      matrix:  # https://docs.djangoproject.com/en/5.0/faq/install/#faq-python-version-support
        django-version: ["42", "50", "51"]
        python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

        exclude:
          - django-version: "42"
            python-version: "3.13"
          - django-version: "50"
            python-version: "3.9"
          - django-version: "50"
            python-version: "3.13"
          - django-version: "51"
            python-version: "3.9"

    steps:
      - uses: actions/checkout@v4
      - name: setup python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install tox
        run: pip install tox
      - name: Run Tests
        env:
          TOXENV: django${{ matrix.django-version }}
        run: tox


================================================
FILE: .gitignore
================================================
*.pyc
build/
dist/
django_libsass.egg-info
MANIFEST


================================================
FILE: CHANGELOG.txt
================================================
Changelog
=========

Unreleased
~~~~~~~~~~~~~~~~

* Added Django 4.1 & 4.2 support
* Added Python 3.10 & 3.11 support
* Drop support for Python 2.7, 3.4, 3.5, 3.6 & 3.7 (EOL)
* Drop support for Django 1.8, 1.9, 1.10, 1.11, 2.2, 3.0 & 3.1 (EOL)

0.9 (08.07.2021)
~~~~~~~~~~~~~~~~
 * Added Django 3.1 and 3.2 support (Awais Qureshi)
 * Added tox and enable Github actions for testing across different Django and Python versions (Awais Qureshi)

0.8 (06.01.2020)
~~~~~~~~~~~~~~~~
 * Added Django 3.0 support (Tobias Kunze, Dan Kingston)
 * Included LICENSE file in distribution (Dougal J. Sutherland)
 * Added LIBSASS_ADDITIONAL_INCLUDE_PATHS setting (Iwan Trofimtschuk)
 * Removed unnecessary quoting from output of `static` function

0.7 (02.05.2016)
~~~~~~~~~~~~~~~~
 * Added LIBSASS_PRECISION setting (Liang-Bo Wang)

0.6 (21.11.2015)
~~~~~~~~~~~~~~~~
 * Fixed call to FilterBase super for django-compressor 1.6 compatibility (Dennis Vermeulen)

0.5 (18.11.2015)
~~~~~~~~~~~~~~~~
 * Added sourcemap support (Saulius Žemaitaitis)
 * Updated the `static` function to use the more versatile django.contrib.staticfiles implementation (Carl Johnson)

0.4 (24.08.2015)
~~~~~~~~~~~~~~~~
 * Added support for custom functions (Alexandre Pocquet)
 * Added a `static` function to generate paths to assets such as images and fonts (Alexandre Pocquet)

0.3 (27.04.2015)
~~~~~~~~~~~~~~~~
 * Enabled source comments when DEBUG is True; can be overridden with the LIBSASS_SOURCE_COMMENTS setting
 * Added LIBSASS_OUTPUT_STYLE setting

0.2 (22.05.2014)
~~~~~~~~~~~~~~~~
 * Made compatible with django-compressor 1.4 and Python 3.

0.1 (05.03.2014)
~~~~~~~~~~~~~~~~
 * Initial release.


================================================
FILE: LICENSE
================================================
Copyright (c) 2014 Torchbox Ltd and individual contributors.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.

    3. Neither the name of Torchbox nor the names of its contributors may be used
       to endorse or promote products derived from this software without
       specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: MANIFEST.in
================================================
include LICENSE


================================================
FILE: README.rst
================================================
django-libsass
==============

A django-compressor filter to compile Sass files using libsass.

Installation
~~~~~~~~~~~~

Starting from a Django project with `django-compressor <https://github.com/django-compressor/django-compressor/>`_ set up::

 pip install django-libsass

and add django_libsass.SassCompiler to your COMPRESS_PRECOMPILERS setting::

 COMPRESS_PRECOMPILERS = (
     ('text/x-scss', 'django_libsass.SassCompiler'),
 )

You can now use the content type text/x-scss on your stylesheets, and have them
compiled seamlessly into CSS::

 {% load compress %}

 {% compress css %}
     <link rel="stylesheet" type="text/x-scss" href="{% static "myapp/css/main.scss" %}" />
 {% endcompress %}


Imports
~~~~~~~

Relative paths in @import lines are followed as you would expect::

 @import "../variables.scss";

Additionally, Django's STATICFILES_FINDERS setting is consulted, and all possible locations
for static files *on the local filesystem* are included on the search path. This makes it
possible to import files across different apps::

 @import "myotherapp/css/widget.scss"


Settings
~~~~~~~~

The following settings can be used to control django-libsass's behaviour:

* ``LIBSASS_SOURCE_COMMENTS`` - whether to enable SASS source comments (adds comments about source lines). Defaults to ``True`` when Django's ``DEBUG`` is ``True``, ``False`` otherwise.
* ``LIBSASS_OUTPUT_STYLE`` - SASS output style. Options are ``'nested'``, ``'expanded'``, ``'compact'`` and ``'compressed'``, although as of libsass 3.0.2 only ``'nested'`` and ``'compressed'`` are implemented. Default is 'nested'. See `SASS documentation for output styles <http://sass-lang.com/documentation/file.SASS_REFERENCE.html#output_style>`_. Note that `django-compressor's settings <http://django-compressor.readthedocs.org/en/latest/settings/>`_ may also affect the formatting of the resulting CSS.
* ``LIBSASS_CUSTOM_FUNCTIONS`` - A mapping of custom functions to be made available within the SASS compiler. By default, a ``static`` function is provided, analogous to Django's ``static`` template tag.
* ``LIBSASS_SOURCEMAPS`` - Enable embedding sourcemaps into file output (default: False)
* ``LIBSASS_PRECISION`` - Number of digits of numerical precision (default: 5)
* ``LIBSASS_ADDITIONAL_INCLUDE_PATHS`` - a list of base paths to be recognised in @import lines, in addition to Django's recognised static file locations


Custom functions
~~~~~~~~~~~~~~~~

The SASS compiler can be extended with custom Python functions defined in the ``LIBSASS_CUSTOM_FUNCTIONS`` setting. By default, a ``static`` function is provided, for generating static paths to resources such as images and fonts::

    .foo {
        background: url(static("myapp/image/bar.png"));
    }

If your ``STATIC_URL`` is '/static/', this will be rendered as::

    .foo {
        background: url("/static/myapp/image/bar.png"));
    }

Why django-libsass?
~~~~~~~~~~~~~~~~~~~

We wanted to use Sass in a Django project without introducing any external (non pip-installable)
dependencies. (Actually, we wanted to use Less, but the same arguments apply...) There are a few
pure Python implementations of Sass and Less, but we found that they invariably didn't match the
behaviour of the reference compilers, either in their handling of @imports or lesser-used CSS
features such as media queries.

`libsass <https://sass-lang.com/libsass>`_ is a mature C/C++ port of the Sass engine, co-developed by the
original creator of Sass, and we can reasonably rely on it to stay in sync with the reference
Sass compiler - and, being C/C++, it's fast. Thanks to Hong Minhee's
`libsass-python <https://github.com/dahlia/libsass-python>`_ project, it has Python bindings and
installs straight from pip.

django-libsass builds on libsass-python to make @import paths aware of Django's staticfiles
mechanism, and provides a filter module for django-compressor which uses the libsass-python API
directly, avoiding the overheads of calling an external executable to do the compilation.


Reporting bugs
~~~~~~~~~~~~~~

Please see the `troubleshooting <https://github.com/torchbox/django-libsass/wiki/Troubleshooting>`_ page for help with some common setup issues.

I do not provide support for getting django-libsass working with your CSS framework of choice. If you believe you've found a bug, please try to isolate it as a minimal reproducible test case before reporting it - ideally this will consist of a few edits / additions to the `hello-django-libsass <https://github.com/gasman/hello-django-libsass>`_ example project. If you cannot demonstrate the problem in a few standalone SCSS files, it is almost certainly not a django-libsass bug - any bug reports that relate to a third-party CSS framework are likely to be closed without further investigation.


Author
~~~~~~

Matt Westcott matthew.westcott@torchbox.com


================================================
FILE: django_libsass.py
================================================
import base64
import json
import os
import re

import sass
from compressor.filters.base import FilterBase
from django.conf import settings
from django.contrib.staticfiles.finders import get_finders
from django.templatetags.static import static as django_static


def static(path):
    """
    Use the Django builtin static file resolver to return an absolute path
    usable as CSS url() argument. Sass equivalent of the 'static' template
    tag.
    """
    return django_static(path)


OUTPUT_STYLE = getattr(settings, 'LIBSASS_OUTPUT_STYLE', 'nested')
SOURCE_COMMENTS = getattr(settings, 'LIBSASS_SOURCE_COMMENTS', settings.DEBUG)
CUSTOM_FUNCTIONS = getattr(settings, 'LIBSASS_CUSTOM_FUNCTIONS', {'static': static})
SOURCEMAPS = getattr(settings, 'LIBSASS_SOURCEMAPS', False)
PRECISION = getattr(settings, 'LIBSASS_PRECISION', None)  # None use libsass default
ADDITIONAL_INCLUDE_PATHS = getattr(settings, 'LIBSASS_ADDITIONAL_INCLUDE_PATHS', None)


INCLUDE_PATHS = None  # populate this on first call to 'get_include_paths'


def get_include_paths():
    """
    Generate a list of include paths that libsass should use to find files
    mentioned in @import lines.
    """
    global INCLUDE_PATHS
    if INCLUDE_PATHS is not None:
        return INCLUDE_PATHS

    include_paths = []

    # Look for staticfile finders that define 'storages'
    for finder in get_finders():
        try:
            storages = finder.storages
        except AttributeError:
            continue

        for storage in storages.values():
            try:
                include_paths.append(storage.path('.'))
            except NotImplementedError:
                # storages that do not implement 'path' do not store files locally,
                # and thus cannot provide an include path
                pass

    global ADDITIONAL_INCLUDE_PATHS
    if ADDITIONAL_INCLUDE_PATHS:
        include_paths.extend(ADDITIONAL_INCLUDE_PATHS)

    INCLUDE_PATHS = include_paths
    return include_paths


def prefix_sourcemap(sourcemap, base_path):
    decoded_sourcemap = json.loads(sourcemap)
    source_urls = []
    include_paths = get_include_paths()

    for source_filename in decoded_sourcemap['sources']:
        # expand source_filename into an absolute file path
        full_source_path = os.path.normpath(os.path.join(base_path, source_filename))

        # look for a path in include_paths that is a prefix of full_source_path
        for path in include_paths:
            if full_source_path.startswith(path):
                # A matching path has been found; take the remainder as a relative path.
                # include_paths entries do not include a trailing slash;
                # [len(path) + 1:] ensures that we trim the path plus trailing slash
                remainder = full_source_path[len(path) + 1:]

                # Invoke the 'static' template tag to turn the relative path into a URL
                source_urls.append(django_static(remainder))
                break
        else:
            # no matching path was found in include_paths; return the original source filename
            # as a fallback
            source_urls.append(source_filename)

    decoded_sourcemap['sources'] = source_urls
    return json.dumps(decoded_sourcemap)


def embed_sourcemap(output, sourcemap):
    encoded_sourcemap = base64.standard_b64encode(
        sourcemap.encode('utf-8')
    )
    sourcemap_fragment = 'sourceMappingURL=data:application/json;base64,{} '\
        .format(encoded_sourcemap.decode('utf-8'))
    url_re = re.compile(r'sourceMappingURL=[^\s]+', re.M)
    output = url_re.sub(sourcemap_fragment, output)

    return output


def compile(**kwargs):
    """Perform sass.compile, but with the appropriate include_paths for Django added"""
    kwargs = kwargs.copy()
    if PRECISION is not None:
        kwargs['precision'] = PRECISION
    kwargs['include_paths'] = (kwargs.get('include_paths') or []) + get_include_paths()

    custom_functions = CUSTOM_FUNCTIONS.copy()
    custom_functions.update(kwargs.get('custom_functions', {}))
    kwargs['custom_functions'] = custom_functions

    if SOURCEMAPS and kwargs.get('filename', None):
        # We need to pass source_map_file to libsass so it generates
        # correct paths to source files.
        base_path = os.path.dirname(kwargs['filename'])
        sourcemap_filename = os.path.join(base_path, 'sourcemap.map')
        kwargs['source_map_filename'] = sourcemap_filename

        libsass_output, sourcemap = sass.compile(**kwargs)
        sourcemap = prefix_sourcemap(sourcemap, base_path)
        output = embed_sourcemap(libsass_output, sourcemap)
    else:
        output = sass.compile(**kwargs)
    return output


class SassCompiler(FilterBase):
    def __init__(self, content, attrs=None, filter_type=None, charset=None, filename=None):
        # FilterBase doesn't handle being passed attrs, so fiddle the signature
        super(SassCompiler, self).__init__(content=content,
                                           filter_type=filter_type,
                                           filename=filename)

    def input(self, **kwargs):
        if self.filename:
            return compile(filename=self.filename,
                           output_style=OUTPUT_STYLE,
                           source_comments=SOURCE_COMMENTS)
        else:
            return compile(string=self.content,
                           output_style=OUTPUT_STYLE)


================================================
FILE: runtests.py
================================================
#!/usr/bin/env python

import argparse
import os
import shutil
import sys
import warnings

from django.core.management import execute_from_command_line

os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.settings'


def make_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument('--deprecation', choices=['pending', 'imminent', 'none'], default='imminent')
    return parser


def parse_args(args=None):
    return make_parser().parse_known_args(args)


def runtests():
    args, rest = parse_args()

    if args.deprecation == 'pending':
        # Show all deprecation warnings
        warnings.simplefilter('default', DeprecationWarning)
        warnings.simplefilter('default', PendingDeprecationWarning)
    elif args.deprecation == 'imminent':
        # Show only imminent deprecation warnings
        warnings.simplefilter('default', DeprecationWarning)
    elif args.deprecation == 'none':
        # Deprecation warnings are ignored by default
        pass

    argv = [sys.argv[0], 'test'] + rest

    try:
        execute_from_command_line(argv)
    finally:
        from tests.settings import STATIC_ROOT
        shutil.rmtree(STATIC_ROOT, ignore_errors=True)


if __name__ == '__main__':
    runtests()


================================================
FILE: setup.cfg
================================================
[metadata]
license-file = LICENSE


================================================
FILE: setup.py
================================================
#!/usr/bin/env python

try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

setup(
    name='django-libsass',
    version='0.9',
    description="A django-compressor filter to compile SASS files using libsass",
    author='Matt Westcott',
    author_email='matthew.westcott@torchbox.com',
    url='https://github.com/torchbox/django-libsass',
    py_modules=['django_libsass'],
    license='BSD',
    long_description=open('README.rst').read(),
    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Environment :: Web Environment',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: BSD License',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.9',
        'Programming Language :: Python :: 3.10',
        'Programming Language :: Python :: 3.11',
        'Programming Language :: Python :: 3.12',
        'Programming Language :: Python :: 3.13',
        'Framework :: Django',
        'Framework :: Django :: 4.2',
        'Framework :: Django :: 5.0',
        'Framework :: Django :: 5.1',
    ],
    python_requires='>=3.9',
    install_requires=[
        "django-compressor>=1.3",
        "libsass>=0.7.0,<1",
    ],
)


================================================
FILE: tests/__init__.py
================================================


================================================
FILE: tests/extra_static/extra.scss
================================================
.extra-style {
    color: blue;
}


================================================
FILE: tests/settings.py
================================================
"""
Django settings for django_libsass tests.

Generated by 'django-admin startproject' using Django 2.0.13.

For more information on this file, see
https://docs.djangoproject.com/en/2.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.0/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'snbicjfchnkjnyhcojinbcojnghjn=*uv2e$gr5-7w2^j2y9y!'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'tests',

    'compressor',

    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'tests.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'test-static')

# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
    'compressor.finders.CompressorFinder',
)

COMPRESS_PRECOMPILERS = (
    ('text/x-scss', 'django_libsass.SassCompiler'),
)

LIBSASS_ADDITIONAL_INCLUDE_PATHS = [
    os.path.join(BASE_DIR, 'tests', 'extra_static'),
]
LIBSASS_SOURCEMAPS = True


================================================
FILE: tests/static/css/imported.scss
================================================
.imported-style {
    color: red;
}


================================================
FILE: tests/static/css/index.scss
================================================
$background-color: #ddffdd;
$foreground-color: #008800;

body {
    background-color: $background-color;

    h1 {
        color: $foreground-color;
    }
}


================================================
FILE: tests/static/css/raw1.css
================================================
.raw-style-1 {
    color: yellow;
}


================================================
FILE: tests/static/css/raw2.css
================================================
.raw-style-2 {
    color: green;
}


================================================
FILE: tests/static/css/with_extra_include.scss
================================================
@import 'extra';


================================================
FILE: tests/static/css/with_import.scss
================================================
@import 'imported';


================================================
FILE: tests/static/css/with_raw_css_import.scss
================================================
@import 'raw1.css';
@import 'raw2';


================================================
FILE: tests/static/css/with_static.scss
================================================
body {
    background-image: url(static('images/my image.jpg'));
}


================================================
FILE: tests/templates/index.html
================================================
{% load compress static %}
<!DOCTYPE HTML>
<html>
    <head>
        <title>Hello django-libsass</title>
        {% compress css %}
            <link rel="stylesheet" type="text/x-scss" href="{% static "css/index.scss" %}" />
        {% endcompress %}
    </head>
    <body>
        <h1>It worked!</h1>
    </body>
</html>


================================================
FILE: tests/tests/__init__.py
================================================


================================================
FILE: tests/tests/test_sass.py
================================================
import os.path
from django.conf import settings
from django.test import TestCase

from django_libsass import compile

class TestSass(TestCase):
    def test_invocation(self):
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)

    def test_import(self):
        result = compile(filename=os.path.join(settings.BASE_DIR, 'tests', 'static', 'css', 'with_import.scss'))
        self.assertIn('.imported-style', result)

    def test_extra_include_path(self):
        result = compile(filename=os.path.join(settings.BASE_DIR, 'tests', 'static', 'css', 'with_extra_include.scss'))
        self.assertIn('.extra-style', result)

    def test_raw_css_import(self):
        result = compile(filename=os.path.join(settings.BASE_DIR, 'tests', 'static', 'css', 'with_raw_css_import.scss'))
        self.assertIn('@import url(raw1.css);', result)
        self.assertIn('.raw-style-2', result)

    def test_static_function(self):
        result = compile(filename=os.path.join(settings.BASE_DIR, 'tests', 'static', 'css', 'with_static.scss'))
        self.assertIn(r'background-image: url(/static/images/my%20image.jpg);', result)


================================================
FILE: tests/urls.py
================================================
from __future__ import absolute_import, unicode_literals

"""hello_django_libsass URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""

from django.urls import path

from tests.views import index


urlpatterns = [
    path('', index),
]


================================================
FILE: tests/views.py
================================================
from django.shortcuts import render


def index(request):
    return render(request, 'index.html')


================================================
FILE: tox.ini
================================================
[tox]
envlist = django{42,50,51}

[testenv]
commands =
    python runtests.py
deps =
    django42: Django>=4.2,<5.0
    django50: Django>=5.0,<5.1
    django51: Django>=5.1,<5.2
Download .txt
gitextract_dyb7hi3g/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── bug_report.md
│   └── workflows/
│       └── test.yml
├── .gitignore
├── CHANGELOG.txt
├── LICENSE
├── MANIFEST.in
├── README.rst
├── django_libsass.py
├── runtests.py
├── setup.cfg
├── setup.py
├── tests/
│   ├── __init__.py
│   ├── extra_static/
│   │   └── extra.scss
│   ├── settings.py
│   ├── static/
│   │   └── css/
│   │       ├── imported.scss
│   │       ├── index.scss
│   │       ├── raw1.css
│   │       ├── raw2.css
│   │       ├── with_extra_include.scss
│   │       ├── with_import.scss
│   │       ├── with_raw_css_import.scss
│   │       └── with_static.scss
│   ├── templates/
│   │   └── index.html
│   ├── tests/
│   │   ├── __init__.py
│   │   └── test_sass.py
│   ├── urls.py
│   └── views.py
└── tox.ini
Download .txt
SYMBOL INDEX (18 symbols across 4 files)

FILE: django_libsass.py
  function static (line 13) | def static(path):
  function get_include_paths (line 33) | def get_include_paths():
  function prefix_sourcemap (line 67) | def prefix_sourcemap(sourcemap, base_path):
  function embed_sourcemap (line 96) | def embed_sourcemap(output, sourcemap):
  function compile (line 108) | def compile(**kwargs):
  class SassCompiler (line 134) | class SassCompiler(FilterBase):
    method __init__ (line 135) | def __init__(self, content, attrs=None, filter_type=None, charset=None...
    method input (line 141) | def input(self, **kwargs):

FILE: runtests.py
  function make_parser (line 14) | def make_parser():
  function parse_args (line 20) | def parse_args(args=None):
  function runtests (line 24) | def runtests():

FILE: tests/tests/test_sass.py
  class TestSass (line 7) | class TestSass(TestCase):
    method test_invocation (line 8) | def test_invocation(self):
    method test_import (line 12) | def test_import(self):
    method test_extra_include_path (line 16) | def test_extra_include_path(self):
    method test_raw_css_import (line 20) | def test_raw_css_import(self):
    method test_static_function (line 25) | def test_static_function(self):

FILE: tests/views.py
  function index (line 4) | def index(request):
Condensed preview — 28 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (26K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 302,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\nPlease see https"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 1064,
    "preview": "name: Unit tests\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n\njobs:\n  build:\n    name: Py"
  },
  {
    "path": ".gitignore",
    "chars": 52,
    "preview": "*.pyc\nbuild/\ndist/\ndjango_libsass.egg-info\nMANIFEST\n"
  },
  {
    "path": "CHANGELOG.txt",
    "chars": 1670,
    "preview": "Changelog\n=========\n\nUnreleased\n~~~~~~~~~~~~~~~~\n\n* Added Django 4.1 & 4.2 support\n* Added Python 3.10 & 3.11 support\n* "
  },
  {
    "path": "LICENSE",
    "chars": 1545,
    "preview": "Copyright (c) 2014 Torchbox Ltd and individual contributors.\nAll rights reserved.\n\nRedistribution and use in source and "
  },
  {
    "path": "MANIFEST.in",
    "chars": 16,
    "preview": "include LICENSE\n"
  },
  {
    "path": "README.rst",
    "chars": 4862,
    "preview": "django-libsass\n==============\n\nA django-compressor filter to compile Sass files using libsass.\n\nInstallation\n~~~~~~~~~~~"
  },
  {
    "path": "django_libsass.py",
    "chars": 5448,
    "preview": "import base64\nimport json\nimport os\nimport re\n\nimport sass\nfrom compressor.filters.base import FilterBase\nfrom django.co"
  },
  {
    "path": "runtests.py",
    "chars": 1228,
    "preview": "#!/usr/bin/env python\n\nimport argparse\nimport os\nimport shutil\nimport sys\nimport warnings\n\nfrom django.core.management i"
  },
  {
    "path": "setup.cfg",
    "chars": 34,
    "preview": "[metadata]\nlicense-file = LICENSE\n"
  },
  {
    "path": "setup.py",
    "chars": 1356,
    "preview": "#!/usr/bin/env python\n\ntry:\n    from setuptools import setup\nexcept ImportError:\n    from distutils.core import setup\n\ns"
  },
  {
    "path": "tests/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/extra_static/extra.scss",
    "chars": 34,
    "preview": ".extra-style {\n    color: blue;\n}\n"
  },
  {
    "path": "tests/settings.py",
    "chars": 3672,
    "preview": "\"\"\"\nDjango settings for django_libsass tests.\n\nGenerated by 'django-admin startproject' using Django 2.0.13.\n\nFor more i"
  },
  {
    "path": "tests/static/css/imported.scss",
    "chars": 36,
    "preview": ".imported-style {\n    color: red;\n}\n"
  },
  {
    "path": "tests/static/css/index.scss",
    "chars": 157,
    "preview": "$background-color: #ddffdd;\n$foreground-color: #008800;\n\nbody {\n    background-color: $background-color;\n\n    h1 {\n     "
  },
  {
    "path": "tests/static/css/raw1.css",
    "chars": 36,
    "preview": ".raw-style-1 {\n    color: yellow;\n}\n"
  },
  {
    "path": "tests/static/css/raw2.css",
    "chars": 35,
    "preview": ".raw-style-2 {\n    color: green;\n}\n"
  },
  {
    "path": "tests/static/css/with_extra_include.scss",
    "chars": 17,
    "preview": "@import 'extra';\n"
  },
  {
    "path": "tests/static/css/with_import.scss",
    "chars": 20,
    "preview": "@import 'imported';\n"
  },
  {
    "path": "tests/static/css/with_raw_css_import.scss",
    "chars": 36,
    "preview": "@import 'raw1.css';\n@import 'raw2';\n"
  },
  {
    "path": "tests/static/css/with_static.scss",
    "chars": 67,
    "preview": "body {\n    background-image: url(static('images/my image.jpg'));\n}\n"
  },
  {
    "path": "tests/templates/index.html",
    "chars": 323,
    "preview": "{% load compress static %}\n<!DOCTYPE HTML>\n<html>\n    <head>\n        <title>Hello django-libsass</title>\n        {% comp"
  },
  {
    "path": "tests/tests/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/tests/test_sass.py",
    "chars": 1160,
    "preview": "import os.path\nfrom django.conf import settings\nfrom django.test import TestCase\n\nfrom django_libsass import compile\n\ncl"
  },
  {
    "path": "tests/urls.py",
    "chars": 804,
    "preview": "from __future__ import absolute_import, unicode_literals\n\n\"\"\"hello_django_libsass URL Configuration\n\nThe `urlpatterns` l"
  },
  {
    "path": "tests/views.py",
    "chars": 99,
    "preview": "from django.shortcuts import render\n\n\ndef index(request):\n    return render(request, 'index.html')\n"
  },
  {
    "path": "tox.ini",
    "chars": 178,
    "preview": "[tox]\nenvlist = django{42,50,51}\n\n[testenv]\ncommands =\n    python runtests.py\ndeps =\n    django42: Django>=4.2,<5.0\n    "
  }
]

About this extraction

This page contains the full source code of the torchbox/django-libsass GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 28 files (23.7 KB), approximately 6.3k tokens, and a symbol index with 18 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!