protibimbok / django-vite-plugin

This plugin configures Vite for use with Django backend.
112 stars 14 forks source link

Can the HTML tag be specified as an argument? #72

Closed are-oh-bee closed 1 week ago

are-oh-bee commented 3 weeks ago

The situation I've encountered is I'd like to use the plugin to dynamically include the path to an image in the same way we're able to include CSS and JS.

Specifically, what I'd like to do is {% vite 'assets/img/favicon.png' type='image/png' rel='shortcut icon' tag='link' %} and have it output:

<link rel="shortcut icon" type="image/png" href="/assets/img/favicon.png" />

instead of:

<script rel="shortcut icon" tag="link" type="image/png" href="/assets/img/favicon.png" />

Proposal

If I modify get_html to be:

def get_html(url: str, attrs: Dict[str, str], custom_tag: str) -> str:
    if custom_tag:
        return f'<{custom_tag} {attrs["css"]} href="{url}" ></{custom_tag}>'
    elif url.endswith('.css'):
        return f'<link {attrs["css"]} href="{url}" />'
    else:
        return f'<script {attrs["js"]} src="{url}"></script>'

modify _make_asset to be:

def _make_asset(asset: str, attrs:Dict[str, str], custom_tag: str = None):
    if CONFIG['DEV_MODE']:
        return get_html_dev(asset, attrs, custom_tag)

    return get_from_manifest(asset, attrs, custom_tag)

and modify __init__ in ViteAssetNode to be:

def __init__(self, assets, attributes, hasDynamicAttr, hasDynamicPath):
    self.assets = assets
    self.attributes = attributes
    self.html = None
    self.hasDynamicPath = hasDynamicPath
    self.customTag = None

    if tag := attributes.get('tag'):
        self.customTag = tag

    if not hasDynamicAttr:
        self.attrs = _make_attrs(attributes)
        self.attributes = None

    if not hasDynamicAttr and not hasDynamicPath:
        self.html   = "".join(_make_asset(asset, self.attrs, custom_tag=self.customTag) for asset in assets)
        self.assets = None

I get the intended results.

Something similar could be done for tag='img', but it would need to output src="{url}" instead of href="{url}", and ideally attrs["img"] would be added to provide full support.

protibimbok commented 3 weeks ago

The intended purpose of this plugin is not loading other assets that are not a subject to vite. Have you ever experienced a situation where things built with vite is not working properly?

are-oh-bee commented 2 weeks ago

Thanks for the reply. Our issue is that we have a centralized folder for images where some are used within the JS and some are used with Django templates. We can configure things to work in a dev environment, or a deployed environment, but not both easily.

I understand this is out of scope for the plugin, so the request can be closed.

protibimbok commented 2 weeks ago

If not being able to configure in both situations comes from the vite side (i.e. it can be loaded in backend easily but the vite build causes problem in deployment) then inshallah we will be do something about it.

RobertoMaurizzi commented 1 week ago

Another similar project has a {% vite_asset '<path to your asset>' %} template tag. It does make sense if you need to use the same assets in both Django templates and Vite JS applications, but I fear it wouldn't help much in this case. It should be possible to have achieve what you need using standard Django features: put your image assets directory in the STATICFILES_DIRS list. @are-oh-bee I imagine that in your vite.config.js you have something like this:

    resolve: {
      alias: {
        '@img': fileURLToPath(new URL('../path/to/where/shared/images/are', import.meta.url))
      }
    }

If that's how it's set up, you should be able to add to your settings.py something to the effect of:

STATICFILES_DIRS = [
    os.path.join(PROJECT_DIR, "./path/to/where/shared/images/are"),
    ...
]