pax_global_header00006660000000000000000000000064134334536260014523gustar00rootroot0000000000000052 comment=a3b00b81749a88f53d5f1129941e60f7c0683788 django-js-asset-1.2.2/000077500000000000000000000000001343345362600145165ustar00rootroot00000000000000django-js-asset-1.2.2/.gitignore000066400000000000000000000002301343345362600165010ustar00rootroot00000000000000*.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-1.2.2/.travis.yml000066400000000000000000000030651343345362600166330ustar00rootroot00000000000000dist: xenial sudo: false language: python python: - 3.7 matrix: fast_finish: true include: - python: 3.7 env: REQ="https://github.com/django/django/archive/master.zip#egg=Django" - python: 3.7 env: REQ="Django>=2.2a1,<3.0" - python: 3.6 env: REQ="Django>=2.2a1,<3.0" - python: 3.5 env: REQ="Django>=2.2a1,<3.0" - python: 3.7 env: REQ="Django>=2.1,<2.2" - python: 3.7 env: REQ="Django>=2.0,<2.1" - python: 3.7 env: REQ="Django>=1.11,<2.0" - python: 3.6 env: REQ="Django>=1.11,<2.0" - python: 3.5 env: REQ="Django>=1.11,<2.0" - python: 3.4 env: REQ="Django>=1.11,<2.0" - python: 2.7 env: REQ="Django>=1.11,<2.0" - python: 3.5 env: REQ="Django>=1.10,<1.11" - python: 2.7 env: REQ="Django>=1.10,<1.11" - python: 3.5 env: REQ="Django>=1.9,<1.10" - python: 2.7 env: REQ="Django>=1.9,<1.10" - python: 3.5 env: REQ="Django>=1.8,<1.9" - python: 3.4 env: REQ="Django>=1.8,<1.9" - python: 2.7 env: REQ="Django>=1.8,<1.9" - python: 3.4 env: REQ="Django>=1.7,<1.8" - python: 2.7 env: REQ="Django>=1.7,<1.8" - python: 3.7 env: REQ="black flake8" install: - pip install black flake8 script: - flake8 . - black --check js_asset tests allow_failures: - env: REQ="https://github.com/django/django/archive/master.zip#egg=Django" install: - pip install $REQ coverage pytz - python setup.py install script: cd tests && ./manage.py test -v2 testapp django-js-asset-1.2.2/CHANGELOG.rst000066400000000000000000000035151343345362600165430ustar00rootroot00000000000000 .. _changelog: Change log ========== `Next version`_ ~~~~~~~~~~~~~~~ - Made ``JS()`` objects hashable so that they can be put into sets in preparation for a possible fix for media ordering in Django #30179. `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 .. _Next version: https://github.com/matthiask/django-js-asset/compare/1.2...master django-js-asset-1.2.2/LICENSE000066400000000000000000000030161343345362600155230ustar00rootroot00000000000000Copyright (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-1.2.2/MANIFEST.in000066400000000000000000000002461343345362600162560ustar00rootroot00000000000000include LICENSE include MANIFEST.in include README.rst recursive-include js_asset/static * recursive-include js_asset/locale * recursive-include js_asset/templates * django-js-asset-1.2.2/README.rst000066400000000000000000000042541343345362600162120ustar00rootroot00000000000000=============================================================================== django-js-asset -- script tag with additional attributes for django.forms.Media =============================================================================== .. image:: https://travis-ci.org/matthiask/django-js-asset.svg?branch=master :target: https://travis-ci.org/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, so specify them as follows:: JS( "https://cdn.example.com/script.js", {"defer": "defer"}, static=False, ) Compatibility ============= At the time of writing this app is compatible with Django 1.7 and better (up to and including the Django master branch), but have a look at the `Travis CI build `_ for definitive answers. django-js-asset-1.2.2/js_asset/000077500000000000000000000000001343345362600163315ustar00rootroot00000000000000django-js-asset-1.2.2/js_asset/__init__.py000066400000000000000000000003271343345362600204440ustar00rootroot00000000000000from __future__ import absolute_import, unicode_literals VERSION = (1, 2, 2) __version__ = ".".join(map(str, VERSION)) try: from js_asset.js import * # noqa except ImportError: # pragma: no cover pass django-js-asset-1.2.2/js_asset/js.py000066400000000000000000000046231343345362600173240ustar00rootroot00000000000000from __future__ import unicode_literals import json from django import VERSION from django.apps import apps from django.forms.utils import flatatt from django.templatetags.static import static from django.utils.html import format_html, mark_safe __all__ = ("JS", "static") if VERSION < (1, 10): # pragma: no cover _static = static def static(path): if apps.is_installed("django.contrib.staticfiles"): from django.contrib.staticfiles.storage import staticfiles_storage return staticfiles_storage.url(path) return _static(path) class JS(object): """ 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=True): self.js = js self.attrs = attrs or {} self.static = static def startswith(self, _): # Masquerade as absolute path so that we are returned as-is. return True def __repr__(self): return "JS({}, {}, static={})".format( self.js, json.dumps(self.attrs, sort_keys=True), self.static ) def __html__(self): js = static(self.js) if self.static else 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 and self.static == other.static ) return self.js == other and not self.attrs and self.static def __hash__(self): return hash((self.js, json.dumps(self.attrs, sort_keys=True), self.static)) django-js-asset-1.2.2/setup.cfg000066400000000000000000000003371343345362600163420ustar00rootroot00000000000000[flake8] exclude=venv,build,docs,.tox ignore=E203,W503 max-complexity=10 max-line-length=88 [bdist_wheel] universal = 1 [coverage:run] branch = True include = *js_asset* omit = *migrations* *tests* *.tox* django-js-asset-1.2.2/setup.py000077500000000000000000000026041343345362600162350ustar00rootroot00000000000000#!/usr/bin/env python from io import open import os from setuptools import setup, find_packages def read(filename): path = os.path.join(os.path.dirname(__file__), filename) with open(path, encoding="utf-8") as handle: return handle.read() setup( name="django-js-asset", version=__import__("js_asset").__version__, description="script tag with additional attributes for django.forms.Media", long_description=read("README.rst"), author="Matthias Kestenholz", author_email="mk@feinheit.ch", url="https://github.com/matthiask/django-js-asset/", license="BSD License", platforms=["OS Independent"], packages=find_packages(exclude=["tests"]), include_package_data=True, classifiers=[ # 'Development Status :: 5 - Production/Stable', "Environment :: Web Environment", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development", "Topic :: Software Development :: Libraries :: Application Frameworks", ], zip_safe=False, tests_require=["Django", "coverage", "pytz"], ) django-js-asset-1.2.2/tests/000077500000000000000000000000001343345362600156605ustar00rootroot00000000000000django-js-asset-1.2.2/tests/.gitignore000066400000000000000000000000241343345362600176440ustar00rootroot00000000000000/.coverage /htmlcov django-js-asset-1.2.2/tests/cov.sh000077500000000000000000000002021343345362600170000ustar00rootroot00000000000000#!/bin/sh venv/bin/coverage run --branch --include="*js_asset/*" --omit="*tests*" ./manage.py test testapp venv/bin/coverage html django-js-asset-1.2.2/tests/manage.py000077500000000000000000000005351343345362600174700ustar00rootroot00000000000000#!/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-1.2.2/tests/requirements.txt000066400000000000000000000000201343345362600211340ustar00rootroot00000000000000Django coverage django-js-asset-1.2.2/tests/testapp/000077500000000000000000000000001343345362600173405ustar00rootroot00000000000000django-js-asset-1.2.2/tests/testapp/__init__.py000066400000000000000000000000001343345362600214370ustar00rootroot00000000000000django-js-asset-1.2.2/tests/testapp/settings.py000066400000000000000000000002731343345362600215540ustar00rootroot00000000000000DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}} INSTALLED_APPS = ["django.contrib.staticfiles"] STATIC_URL = "/static/" SECRET_KEY = "supersikret" django-js-asset-1.2.2/tests/testapp/test_js_asset.py000066400000000000000000000045771343345362600226010ustar00rootroot00000000000000from __future__ import unicode_literals from django.forms import Media from django.test import TestCase from js_asset.js import JS 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( '', # noqa html, ) self.assertInHTML( '', # noqa html, ) self.assertInHTML( '', # noqa html, ) self.assertInHTML( '', # noqa html, ) def test_absolute(self): media = Media(js=[JS("https://cdn.example.org/script.js", static=False)]) html = "%s" % media self.assertInHTML( '', # noqa 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"}, static=True)', # noqa ) 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) django-js-asset-1.2.2/tox.ini000066400000000000000000000012021343345362600160240ustar00rootroot00000000000000[testenv] basepython = python3 [testenv:style] deps = black flake8 changedir = {toxinidir} commands = black setup.py js_asset tests flake8 . skip_install = true # [testenv:docs] # deps = Sphinx # changedir = docs # commands = make html # skip_install = true # whitelist_externals = make [testenv:tests] deps = Django coverage changedir = {toxinidir} skip_install = true commands = coverage run tests/manage.py test -v 2 testapp coverage html [testenv:tests-old] basepython = python2 deps = Django<1.8 changedir = {toxinidir} skip_install = true commands = python tests/manage.py test -v 2 testapp