Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support Jinja2 template backend #136

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Integration of [ViteJS](https://vitejs.dev/) in a Django project.
- [Dev Mode](#dev-mode)
- [Template tags](#template-tags)
- [Custom attributes](#custom-attributes)
- [Jinja2 template backend](#jinja2-template-backend)
- [Vite Legacy Plugin](#vite-legacy-plugin)
- [Multi-app configuration](#multi-app-configuration)
- [Configuration Variables](#configuration-variables)
Expand Down Expand Up @@ -216,6 +217,49 @@ If you want to overrides default attributes just add them like new attributes :

Although it's recommended to keep the default `type="module"` attribute as ViteJS build scripts as ES6 modules.

### Jinja2 template backend

If you are using Django with the Jinja2 template backend then alternative versions of the templatetags are provided, via an Extension.

If you are using [`django-jinja` library](https://niwi.nz/django-jinja/latest/#_add_additional_extensions) then you can:

```python
from django_jinja.builtins import DEFAULT_EXTENSIONS

"OPTIONS": {
"extensions": DEFAULT_EXTENSIONS + [
# Your extensions here...
"django_vite.templatetags.jinja.DjangoViteExtension"
]
}
```

Or for a [vanilla Django + Jinja2 setup](https://docs.djangoproject.com/fr/4.2/topics/templates/#django.template.backends.jinja2.Jinja2) you can do something like:

```python
from django.templatetags.static import static
from django.urls import reverse

from jinja2 import Environment
from django_vite.templatetags.jinja import DjangoViteExtension


def environment(**options):
options.setdefault("extensions", []).append(DjangoViteExtension)
env = Environment(**options)
return env
```

Then usage in your templates is similar, but adjusted as is normal for Jinja2 rather than Django template language.

- Omit the `{% load django_vite %}` which is not needed.
- Replace tag syntax with function calls, e.g.
- `{% vite_react_refresh %}` becomes:
`{{ vite_react_refresh() }}`
- `{% vite_asset '<path to your asset>' foo="bar" %}` becomes:
`{{ vite_asset('<path to your asset>', foo="bar") }}`
etc

## Vite Legacy Plugin

If you want to consider legacy browsers that don't support ES6 modules loading
Expand Down
180 changes: 180 additions & 0 deletions django_vite/templatetags/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
from typing import Dict

from django_vite.core.asset_loader import DjangoViteAssetLoader, DEFAULT_APP_NAME


def vite_hmr_client(app: str = DEFAULT_APP_NAME, **kwargs: Dict[str, str]) -> str:
"""
Generates the script tag for the Vite WS client for HMR.
Only used in development, in production this method returns
an empty string.

Arguments:
config {str} -- Configuration to use.

Returns:
str -- The script tag or an empty string.

Keyword Arguments:
**kwargs {Dict[str, str]} -- Adds new attributes to generated
script tags.
"""

return DjangoViteAssetLoader.instance().generate_vite_ws_client(app, **kwargs)


def vite_asset(
path: str,
app: str = DEFAULT_APP_NAME,
**kwargs: Dict[str, str],
) -> str:
"""
Generates a <script> tag for this JS/TS asset, a <link> tag for
all of its CSS dependencies, and a <link rel="modulepreload">
for all js dependencies, as listed in the manifest file
In development Vite loads all by itself.

Arguments:
path {str} -- Path to a Vite JS/TS asset to include.
config {str} -- Configuration to use.

Returns:
str -- All tags to import this file in your HTML page.

Keyword Arguments:
**kwargs {Dict[str, str]} -- Adds new attributes to generated
script tags.

Raises:
RuntimeError: If cannot find the file path in the
manifest (only in production).

Returns:
str -- The <script> tag and all <link> tags to import this
asset in your page.
"""
assert path is not None
return DjangoViteAssetLoader.instance().generate_vite_asset(path, app, **kwargs)


def vite_preload_asset(path: str, app: str = DEFAULT_APP_NAME) -> str:
"""
Generates preloadmodule tag for this JS/TS asset and preloads
all of its CSS and JS dependencies by reading the manifest
file (for production only).
In development does nothing.

Arguments:
path {str} -- Path to a Vite JS/TS asset to include.

Returns:
str -- All tags to import this file in your HTML page.

Raises:
RuntimeError: If cannot find the file path in the
manifest (only in production).

"""
assert path is not None
return DjangoViteAssetLoader.instance().preload_vite_asset(path, app)


def vite_asset_url(path: str, app: str = DEFAULT_APP_NAME) -> str:
"""
Generates only the URL of an asset managed by ViteJS.
Warning, this function does not generate URLs for dependant assets.

Arguments:
path {str} -- Path to a Vite asset.
config {str} -- Configuration to use.

Raises:
RuntimeError: If cannot find the asset path in the
manifest (only in production).

Returns:
str -- The URL of this asset.
"""
assert path is not None
return DjangoViteAssetLoader.instance().generate_vite_asset_url(path, app)


def vite_legacy_polyfills(app: str = DEFAULT_APP_NAME, **kwargs: Dict[str, str]) -> str:
"""
Generates a <script> tag to the polyfills generated
by '@vitejs/plugin-legacy' if used.
This tag must be included at end of the <body> before including
other legacy scripts.

Arguments:
app {str} -- Configuration to use.

Keyword Arguments:
**kwargs {Dict[str, str]} -- Adds new attributes to generated
script tags.

Raises:
RuntimeError: If polyfills path not found inside
the 'manifest.json' (only in production).

Returns:
str -- The script tag to the polyfills.
"""
return DjangoViteAssetLoader.instance().generate_vite_legacy_polyfills(
app, **kwargs
)


def vite_legacy_asset(
path: str,
app: str = DEFAULT_APP_NAME,
**kwargs: Dict[str, str],
) -> str:
"""
Generates a <script> tag for legacy assets JS/TS
generated by '@vitejs/plugin-legacy'
(in production only, in development do nothing).

Arguments:
path {str} -- Path to a Vite asset to include
(must contains '-legacy' in its name).
app {str} -- Configuration to use.

Keyword Arguments:
**kwargs {Dict[str, str]} -- Adds new attributes to generated
script tags.

Raises:
RuntimeError: If cannot find the asset path in
the manifest (only in production).

Returns:
str -- The script tag of this legacy asset.
"""

assert path is not None

return DjangoViteAssetLoader.instance().generate_vite_legacy_asset(
path, app, **kwargs
)


def vite_react_refresh(
app: str = DEFAULT_APP_NAME,
**kwargs: Dict[str, str],
) -> str:
"""
Generates the script for the Vite React Refresh for HMR.
Only used in development, in production this method returns
an empty string.

Keyword Arguments:
**kwargs {Dict[str, str]} -- Adds new attributes to generated
script tags.

Returns:
str -- The script or an empty string.
"""
return DjangoViteAssetLoader.instance().generate_vite_react_refresh_url(
app, **kwargs
)
Loading
Loading