Skip to content

Commit

Permalink
support Jinja2 template backend, providing extension and tags
Browse files Browse the repository at this point in the history
  • Loading branch information
anentropic committed May 31, 2024
1 parent abf0a5d commit 84c4d8d
Show file tree
Hide file tree
Showing 18 changed files with 1,115 additions and 196 deletions.
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,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

0 comments on commit 84c4d8d

Please sign in to comment.