Skip to content

Commit

Permalink
[Feature] Add assets support
Browse files Browse the repository at this point in the history
  • Loading branch information
SaschaKrug committed Jan 6, 2024
1 parent 91c9052 commit 8a83f24
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

## [0.3.0] - 2024-01-09
- Add assets support
- Add 'is_partial' attribute when rendering partials
- Add support for strings with ' enclosures
- Add PartialResponse class to render partials in views
Expand Down
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,39 @@ def toggle_color_action() -> dict:
</div>
```

# Assets
*Since: 0.3.0*

When registering a component, you can assign JS oder CSS assets to it. You can do this using the `js` or `css` arguments
in the `component_inline_tag` or `component_block_tag`. They will be ordered in the order they are registered,
CSS in front of JS. Duplicates are removed. You can then use the assets via the `assets` tag.

*Hint:* If you want to modify the assets, you can import the `assets` object and modify it before usage.

## Usage
```python
# templatetags/mycomponents.py
from django import template
from django.template.loader import get_template
from django_component_kit import component_inline_tag

register = template.Library()

@register.tag
@component_inline_tag(get_template("mycomponents/card.html"), js=["myjs.js"])
def card() -> dict:
return dict()
```

```html
<!-- templates/index.html -->
{% assets %}
```

### Result
```html
<script src="myjs.js" defer></script>
```

# Contribution

Expand Down
6 changes: 4 additions & 2 deletions django_component_kit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from .tags import do_merge_attrs, do_slot, do_render_slot, do_partial
from .tags import do_merge_attrs, do_slot, do_render_slot, do_partial, do_assets
from .decorators import component_inline_tag, component_block_tag
from .partials import render_partial_from_template
from .partials import render_partial_from_template, PartialResponse

__all__ = [
"do_merge_attrs",
"do_slot",
"do_render_slot",
"do_assets",
"component_inline_tag",
"component_block_tag",
"do_partial",
"render_partial_from_template",
"PartialResponse",
]
25 changes: 25 additions & 0 deletions django_component_kit/assets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""
Assets management for Django Component Kit.
"""
from typing import Iterable


class AssetRegistry:
"""Registry for assets"""

def __init__(self):
self.js = set()
self.css = set()

def add_js(self, js_list: Iterable[str] | None):
"""Add JS files"""
js_list = js_list or []
self.js.update([f'<script src="{js}" defer></script>' for js in js_list])

def add_css(self, css_list: Iterable[str] | None):
"""Add CSS files"""
css_list = css_list or []
self.css.update([f'<link crossorigin="anonymous" href="{css}" rel="stylesheet">' for css in css_list])


assets = AssetRegistry()
11 changes: 9 additions & 2 deletions django_component_kit/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.template import NodeList, TemplateSyntaxError
from django.template.base import Parser, Token, Template

from django_component_kit.assets import assets
from django_component_kit.attributes import split_attributes
from django_component_kit.nodes import ComponentNode, SlotNodeList, SlotNode, INNER_SLOT_NAME
from django_component_kit.utils import token_kwargs
Expand Down Expand Up @@ -49,9 +50,12 @@ def _parse_bits(bits: list, parser: Parser, nodelist: NodeList) -> tuple:
return slots, attrs


def component_inline_tag(template: Template, partial: str = None) -> callable:
def component_inline_tag(template: Template, partial: str = None, js: list = None, css: list = None) -> callable:
"""Decorator for creating an inline component tag."""

assets.add_js(js)
assets.add_css(css)

def dec(func):
def do_component(parser: Parser, token: Token) -> ComponentNode:
"""Creates a ComponentNode for the inline component tag."""
Expand All @@ -66,9 +70,12 @@ def do_component(parser: Parser, token: Token) -> ComponentNode:
return dec


def component_block_tag(template: Template, partial: str = None) -> callable:
def component_block_tag(template: Template, partial: str = None, js: list = None, css: list = None) -> callable:
"""Decorator for creating a block component tag."""

assets.add_js(js)
assets.add_css(css)

def dec(func):
def do_component(parser: Parser, token: Token) -> ComponentNode:
"""Creates a ComponentNode for the block component tag."""
Expand Down
9 changes: 9 additions & 0 deletions django_component_kit/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from django.template.base import FilterExpression, Node, NodeList
from django.utils.safestring import SafeString

from django_component_kit.assets import assets
from django_component_kit.attributes import AttributeBag, attributes_to_string, merge_attributes, append_attributes
from django_component_kit.partials import render_partial_from_template

Expand Down Expand Up @@ -172,3 +173,11 @@ def render(self, context: Context) -> str:
attrs = merge_attributes(default_attrs, bound_attributes)
attrs = append_attributes(attrs, append_attrs)
return attributes_to_string(attrs)


class AssetsNode(Node):
"""Represents an asset node in the template."""

def render(self, _):
"""Renders all assets."""
return "\n".join(assets.js.union(assets.css))
7 changes: 6 additions & 1 deletion django_component_kit/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.template.base import Parser, Token

from django_component_kit.attributes import split_attributes
from django_component_kit.nodes import MergeAttrsNode, RenderSlotNode, SlotNode
from django_component_kit.nodes import MergeAttrsNode, RenderSlotNode, SlotNode, AssetsNode
from django_component_kit.partials import PartialNode
from django_component_kit.utils import attribute_re, token_kwargs

Expand Down Expand Up @@ -117,3 +117,8 @@ def do_partial(parser: Parser, token: Token) -> PartialNode:
nodelist = parser.parse(("endpartial",))
parser.delete_first_token()
return PartialNode(partial_name, inline, nodelist)


def do_assets(*_) -> AssetsNode:
"""Add JS and CSS assets."""
return AssetsNode()
4 changes: 2 additions & 2 deletions django_component_kit/templatetags/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"""
from django import template

from django_component_kit.tags import do_merge_attrs, do_render_slot, do_slot, do_partial

from django_component_kit.tags import do_merge_attrs, do_render_slot, do_slot, do_partial, do_assets

register = template.Library()
register.tag("merge_attrs", do_merge_attrs)
register.tag("render_slot", do_render_slot)
register.tag("slot", do_slot)
register.tag("partial", do_partial)
register.tag("assets", do_assets)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "django-component-kit"
version = "0.2.1"
version = "0.3.0"
description = "A lightweight library for flexible Django component building, following Django's principles."
authors = ["Sascha Krug"]
license = "MIT"
Expand Down

0 comments on commit 8a83f24

Please sign in to comment.