pax_global_header 0000666 0000000 0000000 00000000064 14536120165 0014515 g ustar 00root root 0000000 0000000 52 comment=18496bebb174bcc0f818005c4f56090b700287c2
django-js-asset-2.2/ 0000775 0000000 0000000 00000000000 14536120165 0014351 5 ustar 00root root 0000000 0000000 django-js-asset-2.2/.editorconfig 0000664 0000000 0000000 00000000310 14536120165 0017020 0 ustar 00root root 0000000 0000000 # top-most EditorConfig file
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[*.py]
indent_size = 4
django-js-asset-2.2/.github/ 0000775 0000000 0000000 00000000000 14536120165 0015711 5 ustar 00root root 0000000 0000000 django-js-asset-2.2/.github/workflows/ 0000775 0000000 0000000 00000000000 14536120165 0017746 5 ustar 00root root 0000000 0000000 django-js-asset-2.2/.github/workflows/tests.yml 0000664 0000000 0000000 00000001657 14536120165 0021644 0 ustar 00root root 0000000 0000000 name: Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: "37 1 1 * *"
jobs:
tests:
name: Python ${{ matrix.python-version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip wheel setuptools tox
- name: Run tox targets for ${{ matrix.python-version }}
run: |
ENV_PREFIX=$(tr -C -d "0-9" <<< "${{ matrix.python-version }}")
TOXENV=$(tox --listenvs | grep "^py$ENV_PREFIX" | tr '\n' ',') python -m tox
django-js-asset-2.2/.gitignore 0000664 0000000 0000000 00000000230 14536120165 0016334 0 ustar 00root root 0000000 0000000 *.py?
*~
*.sw?
\#*#
/secrets.py
.DS_Store
._*
/*.egg-info
/MANIFEST
/_build
/build
/dist
tests/test.zip
/docs/_build
/.eggs
.coverage
htmlcov
venv
.tox
django-js-asset-2.2/.pre-commit-config.yaml 0000664 0000000 0000000 00000002346 14536120165 0020637 0 ustar 00root root 0000000 0000000 exclude: ".yarn/|yarn.lock|\\.min\\.(css|js)$"
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-added-large-files
- id: check-builtin-literals
- id: check-executables-have-shebangs
- id: check-merge-conflict
- id: check-toml
- id: check-yaml
- id: detect-private-key
- id: end-of-file-fixer
- id: mixed-line-ending
- id: trailing-whitespace
- repo: https://github.com/adamchainz/django-upgrade
rev: 1.15.0
hooks:
- id: django-upgrade
args: [--target-version, "3.2"]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.1.7"
hooks:
- id: ruff
- repo: https://github.com/psf/black
rev: 23.12.0
hooks:
- id: black
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v4.0.0-alpha.4
hooks:
- id: prettier
entry: env PRETTIER_LEGACY_CLI=1 prettier
args: [--list-different, --no-semi]
exclude: "^conf/|.*\\.html$"
- repo: https://github.com/tox-dev/pyproject-fmt
rev: 1.5.3
hooks:
- id: pyproject-fmt
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.15
hooks:
- id: validate-pyproject
django-js-asset-2.2/CHANGELOG.rst 0000664 0000000 0000000 00000006021 14536120165 0016371 0 ustar 00root root 0000000 0000000
.. _changelog:
Change log
==========
Next version
~~~~~~~~~~~~
2.2 (2023-12-12)
~~~~~~~~~~~~~~~~
- Started running the tests periodically to detect breakages early.
- Added Django 5.0, Python 3.12.
- Fixed building with hatchling 1.19. Thanks Michał Górny!
2.1 (2023-06-28)
~~~~~~~~~~~~~~~~
- Added Django 4.1, 4.2 and Python 3.11 to the CI.
- Removed the pytz dependency from the tests.
- Dropped Python < 3.8, Django < 3.2 from the CI.
- Switched to hatchling and ruff.
`2.0`_ (2022-02-10)
~~~~~~~~~~~~~~~~~~~
.. _2.0: https://github.com/matthiask/django-js-asset/compare/1.2...2.0
- Raised the minimum supported versions of Python to 3.6, Django to 2.2.
- Added pre-commit.
- Replaced the explicit configuration of whether ``static()`` should be used or
not with automatic configuration. The ``static`` argument is still accepted
but ignored and will be removed at a later time.
- Added support for boolean attributes when using Django 4.1 or better.
Released as 1.2.1 and 1.2.2:
----------------------------
- Made ``JS()`` objects hashable so that they can be put into sets in
preparation for a possible fix for media ordering in Django #30179.
- Confirmed support for Django 3.0 and 3.1a1.
- Django dropped ``type="text/javascript"`` in 3.1, changed our tests to
pass again.
- Switched from Travis CI to GitHub actions.
- Dropped Django 1.7 from the CI jobs list because it somehow didn't
discover our tests.
- Renamed the main branch to ``main``.
- Added CI testing for Django 3.2.
`1.2`_ (2019-02-08)
~~~~~~~~~~~~~~~~~~~
- Reformatted the code using Black.
- Added equality of ``JS()`` objects to avoid adding the same script
more than once in the same configuration.
- Determine the ``static`` callable at module import time, not each time
a static path is generated.
- Customized the ``repr()`` of ``JS()`` objects.
- Added Python 3.7 and Django 2.2 to the test matrix.
`1.1`_ (2018-04-19)
~~~~~~~~~~~~~~~~~~~
- Added support for skipping ``static()``, mostly useful when adding
external scripts via ``JS()`` (e.g for adding ``defer="defer"``).
- Made the attributes dictionary optional.
`1.0`_ (2018-01-16)
~~~~~~~~~~~~~~~~~~~
- Added an export of the ``js_asset.static()`` helper (which does the
right thing regarding ``django.contrib.staticfiles``)
- Fixed the documentation to not mention internal (and removed) API of
Django's ``Media()`` class.
- Switched to using tox_ for running tests and style checks locally.
- Added more versions of Python and Django to the CI matrix.
`0.1`_ (2017-04-19)
~~~~~~~~~~~~~~~~~~~
- Initial public release extracted from django-content-editor_.
.. _Django: https://www.djangoproject.com/
.. _django-content-editor: https://django-content-editor.readthedocs.io/
.. _tox: https://tox.readthedocs.io/
.. _0.1: https://github.com/matthiask/django-js-asset/commit/e335c79a87
.. _1.0: https://github.com/matthiask/django-js-asset/compare/0.1...1.0
.. _1.1: https://github.com/matthiask/django-js-asset/compare/1.0...1.1
.. _1.2: https://github.com/matthiask/django-js-asset/compare/1.1...1.2
django-js-asset-2.2/LICENSE 0000664 0000000 0000000 00000003016 14536120165 0015356 0 ustar 00root root 0000000 0000000 Copyright (c) 2016, FEINHEIT AG 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 FEINHEIT GmbH 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.
django-js-asset-2.2/README.rst 0000664 0000000 0000000 00000004362 14536120165 0016045 0 ustar 00root root 0000000 0000000 ===============================================================================
django-js-asset -- script tag with additional attributes for django.forms.Media
===============================================================================
.. image:: https://github.com/matthiask/django-js-asset/workflows/Tests/badge.svg
:target: https://github.com/matthiask/django-js-asset
Usage
=====
Use this to insert a script tag via ``forms.Media`` containing additional
attributes (such as ``id`` and ``data-*`` for CSP-compatible data
injection.):
.. code-block:: python
from js_asset import JS
forms.Media(js=[
JS("asset.js", {
"id": "asset-script",
"data-answer": "42",
}),
])
The rendered media tag (via ``{{ media.js }}`` or ``{{ media }}`` will
now contain a script tag as follows, without line breaks:
.. code-block:: html
The attributes are automatically escaped. The data attributes may now be
accessed inside ``asset.js``:
.. code-block:: javascript
var answer = document.querySelector("#asset-script").dataset.answer;
Also, because the implementation of ``static`` differs between supported
Django versions (older do not take the presence of
``django.contrib.staticfiles`` in ``INSTALLED_APPS`` into account), a
``js_asset.static`` function is provided which does the right thing
automatically.
When adding external script assets, you should pass ``static=False`` to the
``JS`` object to avoid passing the script URL through ``static()``. In this
case, you probably want to add ``defer`` or ``async``, and maybe also
``integrity`` and ``crossorigin`` attributes. Please note that boolean
attributes are not properly supported when using Django before 4.1 so specify
them as follows:
.. code-block:: python
JS(
"https://cdn.example.com/script.js",
{"defer": "defer"},
static=False,
)
Compatibility
=============
At the time of writing this app is compatible with Django 1.8 and better
(up to and including the Django master branch), but have a look at the
`tox configuration
`_ for
definitive answers.
django-js-asset-2.2/js_asset/ 0000775 0000000 0000000 00000000000 14536120165 0016164 5 ustar 00root root 0000000 0000000 django-js-asset-2.2/js_asset/__init__.py 0000664 0000000 0000000 00000000176 14536120165 0020301 0 ustar 00root root 0000000 0000000 __version__ = "2.2.0"
import contextlib
with contextlib.suppress(ImportError):
from js_asset.js import * # noqa: F403
django-js-asset-2.2/js_asset/js.py 0000664 0000000 0000000 00000005243 14536120165 0017156 0 ustar 00root root 0000000 0000000 import json
import warnings
from django import VERSION
from django.forms.utils import flatatt
from django.templatetags.static import static
from django.utils.html import format_html, html_safe, mark_safe
__all__ = ("JS", "static")
_sentinel = object()
class JS:
"""
Use this to insert a script tag via ``forms.Media`` containing additional
attributes (such as ``id`` and ``data-*`` for CSP-compatible data
injection.)::
forms.Media(js=[
JS('asset.js', {
'id': 'asset-script',
'data-answer': '"42"',
}),
])
The rendered media tag (via ``{{ media.js }}`` or ``{{ media }}`` will
now contain a script tag as follows, without line breaks::
The attributes are automatically escaped. The data attributes may now be
accessed inside ``asset.js``::
var answer = document.querySelector('#asset-script').dataset.answer;
"""
def __init__(self, js, attrs=None, static=_sentinel):
self.js = js
self.attrs = attrs or {}
if static is not _sentinel:
warnings.warn(
"JS automatically determines whether it received an absolute"
" path or not. Stop passing the 'static' argument please.",
DeprecationWarning,
stacklevel=2,
)
def startswith(self, _):
# Masquerade as absolute path so that we are returned as-is.
return True
def __repr__(self):
return f"JS({self.js}, {json.dumps(self.attrs, sort_keys=True)})"
if VERSION >= (4, 1):
def __str__(self):
return format_html(
'',
self.js
if self.js.startswith(("http://", "https://", "/"))
else static(self.js),
mark_safe(flatatt(self.attrs)),
)
else:
def __html__(self):
js = (
self.js
if self.js.startswith(("http://", "https://", "/"))
else static(self.js)
)
return (
format_html('{}"{}', js, mark_safe(flatatt(self.attrs)))[:-1]
if self.attrs
else js
)
def __eq__(self, other):
if isinstance(other, JS):
return self.js == other.js and self.attrs == other.attrs
return self.js == other and not self.attrs
def __hash__(self):
return hash((self.js, json.dumps(self.attrs, sort_keys=True)))
if VERSION >= (4, 1):
JS = html_safe(JS)
django-js-asset-2.2/pyproject.toml 0000664 0000000 0000000 00000004366 14536120165 0017276 0 ustar 00root root 0000000 0000000 [build-system]
build-backend = "hatchling.build"
requires = [
"hatchling",
]
[project]
name = "django-js-asset"
description = "script tag with additional attributes for django.forms.Media"
readme = "README.rst"
license = {text = "BSD-3-Clause"}
authors = [
{ name = "Matthias Kestenholz", email = "mk@feinheit.ch" },
]
requires-python = ">=3.8"
classifiers = [
"Environment :: Web Environment",
"Framework :: Django",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
"Topic :: Software Development",
"Topic :: Software Development :: Libraries :: Application Frameworks",
]
dynamic = [
"version",
]
dependencies = [
"Django>=3.2",
]
[project.optional-dependencies]
tests = [
"coverage",
]
[project.urls]
Homepage = "https://github.com/matthiask/django-js-asset/"
[tool.hatch.build.targets.wheel]
packages = ["js_asset"]
[tool.hatch.version]
path = "js_asset/__init__.py"
[tool.ruff]
extend-select = [
# pyflakes, pycodestyle
"F", "E", "W",
# mmcabe
"C90",
# isort
"I",
# pep8-naming
"N",
# pyupgrade
"UP",
# flake8-2020
"YTT",
# flake8-boolean-trap
"FBT",
# flake8-bugbear
"B",
# flake8-comprehensions
"C4",
# flake8-django
"DJ",
# flake8-logging-format
"G",
# flake8-pie
"PIE",
# flake8-simplify
"SIM",
# flake8-tidy-imports
"TID",
# flake8-gettext
"INT",
# pygrep-hooks
"PGH",
# pylint
"PL",
# unused noqa
"RUF100",
]
extend-ignore = [
# Allow zip() without strict=
"B905",
# No line length errors
"E501",
]
fix = true
show-fixes = true
target-version = "py38"
[tool.ruff.isort]
combine-as-imports = true
lines-after-imports = 2
[tool.ruff.mccabe]
max-complexity = 15
[tool.ruff.per-file-ignores]
"*/migrat*/*" = [
# Allow using PascalCase model names in migrations
"N806",
# Ignore the fact that migration files are invalid module names
"N999",
]
django-js-asset-2.2/tests/ 0000775 0000000 0000000 00000000000 14536120165 0015513 5 ustar 00root root 0000000 0000000 django-js-asset-2.2/tests/.gitignore 0000664 0000000 0000000 00000000024 14536120165 0017477 0 ustar 00root root 0000000 0000000 /.coverage
/htmlcov
django-js-asset-2.2/tests/cov.sh 0000775 0000000 0000000 00000000202 14536120165 0016633 0 ustar 00root root 0000000 0000000 #!/bin/sh
venv/bin/coverage run --branch --include="*js_asset/*" --omit="*tests*" ./manage.py test testapp
venv/bin/coverage html
django-js-asset-2.2/tests/manage.py 0000775 0000000 0000000 00000000535 14536120165 0017323 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
import os
import sys
from os.path import abspath, dirname
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testapp.settings")
sys.path.insert(0, dirname(dirname(abspath(__file__))))
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
django-js-asset-2.2/tests/requirements.txt 0000664 0000000 0000000 00000000020 14536120165 0020767 0 ustar 00root root 0000000 0000000 Django
coverage
django-js-asset-2.2/tests/testapp/ 0000775 0000000 0000000 00000000000 14536120165 0017173 5 ustar 00root root 0000000 0000000 django-js-asset-2.2/tests/testapp/__init__.py 0000664 0000000 0000000 00000000000 14536120165 0021272 0 ustar 00root root 0000000 0000000 django-js-asset-2.2/tests/testapp/settings.py 0000664 0000000 0000000 00000000273 14536120165 0021407 0 ustar 00root root 0000000 0000000 DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}}
INSTALLED_APPS = ["django.contrib.staticfiles"]
STATIC_URL = "/static/"
SECRET_KEY = "supersikret"
django-js-asset-2.2/tests/testapp/test_js_asset.py 0000664 0000000 0000000 00000005334 14536120165 0022424 0 ustar 00root root 0000000 0000000 from unittest import skipIf
import django
from django.forms import Media
from django.test import TestCase
from js_asset.js import JS
CSS_TYPE = ' type="text/css"' if django.VERSION < (4, 1) else ""
JS_TYPE = ' type="text/javascript"' if django.VERSION < (3, 1) else ""
class AssetTest(TestCase):
def test_asset(self):
media = Media(
css={"print": ["app/print.css"]},
js=[
"app/test.js",
JS("app/asset.js", {"id": "asset-script", "data-the-answer": 42}),
JS("app/asset-without.js", {}),
],
)
html = "%s" % media
# print(html)
self.assertInHTML(
f'',
html,
)
self.assertInHTML(
f'',
html,
)
self.assertInHTML(
f'',
html,
)
self.assertInHTML(
f'',
html,
)
def test_absolute(self):
media = Media(js=[JS("https://cdn.example.org/script.js", static=False)])
html = "%s" % media
self.assertInHTML(
f'',
html,
)
def test_asset_merging(self):
media1 = Media(js=["thing.js", JS("other.js"), "some.js"])
media2 = Media(js=["thing.js", JS("other.js"), "some.js"])
media = media1 + media2
self.assertEqual(len(media._js), 3)
self.assertEqual(media._js[0], "thing.js")
self.assertEqual(media._js[2], "some.js")
def test_repr(self):
self.assertEqual(
repr(
JS("app/asset.js", {"id": "asset-script", "data-the-answer": 42})
).lstrip("u"),
'JS(app/asset.js, {"data-the-answer": 42, "id": "asset-script"})',
)
def test_set(self):
media = [
JS("app/asset.js", {"id": "asset-script", "data-the-answer": 42}),
JS("app/asset.js", {"id": "asset-script", "data-the-answer": 42}),
JS("app/asset.js", {"id": "asset-script", "data-the-answer": 43}),
]
self.assertEqual(len(set(media)), 2)
@skipIf(
django.VERSION < (4, 1),
"django-js-asset doesn't support boolean attributes yet",
)
def test_boolean_attributes(self):
self.assertEqual(
str(JS("app/asset.js", {"bool": True, "cool": False})),
'',
)
django-js-asset-2.2/tox.ini 0000664 0000000 0000000 00000000715 14536120165 0015667 0 ustar 00root root 0000000 0000000 [tox]
envlist =
py{38,39,310}-dj{32,41,42}
py{310,311}-dj{32,41,42,50,main}
py{312}-dj{42,50,main}
[testenv]
usedevelop = true
extras = tests
commands =
python -Wd {envbindir}/coverage run tests/manage.py test -v2 --keepdb {posargs:testapp}
coverage report -m
deps =
dj32: Django>=3.2,<4.0
dj41: Django>=4.1,<4.2
dj42: Django>=4.2,<5.0
dj50: Django>=5.0,<5.1
djmain: https://github.com/django/django/archive/main.tar.gz