diff --git a/dev/SUMMARY/index.html b/dev/SUMMARY/index.html index cfed22af..566e7763 100644 --- a/dev/SUMMARY/index.html +++ b/dev/SUMMARY/index.html @@ -1 +1 @@ - SUMMARY - Django-Components
\ No newline at end of file + SUMMARY - Django-Components
\ No newline at end of file diff --git a/dev/concepts/advanced/authoring_component_libraries/index.html b/dev/concepts/advanced/authoring_component_libraries/index.html index 6600c6a3..e494fb68 100644 --- a/dev/concepts/advanced/authoring_component_libraries/index.html +++ b/dev/concepts/advanced/authoring_component_libraries/index.html @@ -1,4 +1,4 @@ - Authoring component libraries - Django-Components
Skip to content

Authoring component libraries

You can publish and share your components for others to use. Here are the steps to do so:

Writing component librariesΒ€

  1. Create a Django project with a similar structure:

    project/
    + Authoring component libraries - Django-Components      

    Authoring component libraries

    You can publish and share your components for others to use. Here are the steps to do so:

    Writing component librariesΒ€

    1. Create a Django project with a similar structure:

      project/
         |--  myapp/
           |--  __init__.py
           |--  apps.py
      diff --git a/dev/concepts/advanced/component_registry/index.html b/dev/concepts/advanced/component_registry/index.html
      index d12720de..6cd11203 100644
      --- a/dev/concepts/advanced/component_registry/index.html
      +++ b/dev/concepts/advanced/component_registry/index.html
      @@ -1,4 +1,4 @@
      - Registering components - Django-Components      

      Registering components

      In previous examples you could repeatedly see us using @register() to "register" the components. In this section we dive deeper into what it actually means and how you can manage (add or remove) components.

      As a reminder, we may have a component like this:

      from django_components import Component, register
      + Registering components - Django-Components      

      Registering components

      In previous examples you could repeatedly see us using @register() to "register" the components. In this section we dive deeper into what it actually means and how you can manage (add or remove) components.

      As a reminder, we may have a component like this:

      from django_components import Component, register
       
       @register("calendar")
       class Calendar(Component):
      diff --git a/dev/concepts/advanced/hooks/index.html b/dev/concepts/advanced/hooks/index.html
      index 757bdf2b..2ba64917 100644
      --- a/dev/concepts/advanced/hooks/index.html
      +++ b/dev/concepts/advanced/hooks/index.html
      @@ -1,4 +1,4 @@
      - Lifecycle hooks - Django-Components      

      Lifecycle hooks

      New in version 0.96

      Component hooks are functions that allow you to intercept the rendering process at specific positions.

      Available hooksΒ€

      • on_render_before
      def on_render_before(
      + Lifecycle hooks - Django-Components      

      Lifecycle hooks

      New in version 0.96

      Component hooks are functions that allow you to intercept the rendering process at specific positions.

      Available hooksΒ€

      • on_render_before
      def on_render_before(
           self: Component,
           context: Context,
           template: Template
      diff --git a/dev/concepts/advanced/provide_inject/index.html b/dev/concepts/advanced/provide_inject/index.html
      index b2b75ec8..c81e0088 100644
      --- a/dev/concepts/advanced/provide_inject/index.html
      +++ b/dev/concepts/advanced/provide_inject/index.html
      @@ -1,4 +1,4 @@
      - Prop drilling and provide / inject - Django-Components      

      Prop drilling and provide / inject

      New in version 0.80:

      Django components supports the provide / inject or ContextProvider pattern with the combination of:

      1. {% provide %} tag
      2. inject() method of the Component class

      What is "prop drilling"?Β€

      Prop drilling refers to a scenario in UI development where you need to pass data through many layers of a component tree to reach the nested components that actually need the data.

      Normally, you'd use props to send data from a parent component to its children. However, this straightforward method becomes cumbersome and inefficient if the data has to travel through many levels or if several components scattered at different depths all need the same piece of information.

      This results in a situation where the intermediate components, which don't need the data for their own functioning, end up having to manage and pass along these props. This clutters the component tree and makes the code verbose and harder to manage.

      A neat solution to avoid prop drilling is using the "provide and inject" technique.

      With provide / inject, a parent component acts like a data hub for all its descendants. This setup allows any component, no matter how deeply nested it is, to access the required data directly from this centralized provider without having to messily pass props down the chain. This approach significantly cleans up the code and makes it easier to maintain.

      This feature is inspired by Vue's Provide / Inject and React's Context / useContext.

      How to use provide / injectΒ€

      As the name suggest, using provide / inject consists of 2 steps

      1. Providing data
      2. Injecting provided data

      For examples of advanced uses of provide / inject, see this discussion.

      Using {% provide %} tagΒ€

      First we use the {% provide %} tag to define the data we want to "provide" (make available).

      {% provide "my_data" key="hi" another=123 %}
      + Prop drilling and provide / inject - Django-Components      

      Prop drilling and provide / inject

      New in version 0.80:

      Django components supports the provide / inject or ContextProvider pattern with the combination of:

      1. {% provide %} tag
      2. inject() method of the Component class

      What is "prop drilling"?Β€

      Prop drilling refers to a scenario in UI development where you need to pass data through many layers of a component tree to reach the nested components that actually need the data.

      Normally, you'd use props to send data from a parent component to its children. However, this straightforward method becomes cumbersome and inefficient if the data has to travel through many levels or if several components scattered at different depths all need the same piece of information.

      This results in a situation where the intermediate components, which don't need the data for their own functioning, end up having to manage and pass along these props. This clutters the component tree and makes the code verbose and harder to manage.

      A neat solution to avoid prop drilling is using the "provide and inject" technique.

      With provide / inject, a parent component acts like a data hub for all its descendants. This setup allows any component, no matter how deeply nested it is, to access the required data directly from this centralized provider without having to messily pass props down the chain. This approach significantly cleans up the code and makes it easier to maintain.

      This feature is inspired by Vue's Provide / Inject and React's Context / useContext.

      How to use provide / injectΒ€

      As the name suggest, using provide / inject consists of 2 steps

      1. Providing data
      2. Injecting provided data

      For examples of advanced uses of provide / inject, see this discussion.

      Using {% provide %} tagΒ€

      First we use the {% provide %} tag to define the data we want to "provide" (make available).

      {% provide "my_data" key="hi" another=123 %}
           {% component "child" / %}  <--- Can access "my_data"
       {% endprovide %}
       
      diff --git a/dev/concepts/advanced/rendering_js_css/index.html b/dev/concepts/advanced/rendering_js_css/index.html
      index d376b526..bd8e3a55 100644
      --- a/dev/concepts/advanced/rendering_js_css/index.html
      +++ b/dev/concepts/advanced/rendering_js_css/index.html
      @@ -1,4 +1,4 @@
      - Rendering JS / CSS - Django-Components      

      Rendering JS / CSS

      JS and CSS output locationsΒ€

      If:

      1. Your components use JS and CSS via any of:
      2. And you use the ComponentDependencyMiddleware middleware

      Then, by default, the components' JS and CSS will be automatically inserted into the HTML:

      • CSS styles will be inserted at the end of the <head>
      • JS scripts will be inserted at the end of the <body>

      If you want to place the dependencies elsewhere in the HTML, you can override the locations by inserting following Django template tags:

      So if you have a component with JS and CSS:

      from django_components import Component, types
      + Rendering JS / CSS - Django-Components      

      Rendering JS / CSS

      JS and CSS output locationsΒ€

      If:

      1. Your components use JS and CSS via any of:
      2. And you use the ComponentDependencyMiddleware middleware

      Then, by default, the components' JS and CSS will be automatically inserted into the HTML:

      • CSS styles will be inserted at the end of the <head>
      • JS scripts will be inserted at the end of the <body>

      If you want to place the dependencies elsewhere in the HTML, you can override the locations by inserting following Django template tags:

      So if you have a component with JS and CSS:

      from django_components import Component, types
       
       class MyButton(Component):
           template: types.django_html = """
      diff --git a/dev/concepts/advanced/tag_formatter/index.html b/dev/concepts/advanced/tag_formatter/index.html
      index 01b555ea..e86783c7 100644
      --- a/dev/concepts/advanced/tag_formatter/index.html
      +++ b/dev/concepts/advanced/tag_formatter/index.html
      @@ -1,4 +1,4 @@
      - Tag formatters - Django-Components      

      Tag formatters

      Customizing component tags with TagFormatterΒ€

      New in version 0.89

      By default, components are rendered using the pair of {% component %} / {% endcomponent %} template tags:

      {% component "button" href="..." disabled %}
      + Tag formatters - Django-Components      

      Tag formatters

      Customizing component tags with TagFormatterΒ€

      New in version 0.89

      By default, components are rendered using the pair of {% component %} / {% endcomponent %} template tags:

      {% component "button" href="..." disabled %}
       Click me!
       {% endcomponent %}
       
      diff --git a/dev/concepts/advanced/typing_and_validation/index.html b/dev/concepts/advanced/typing_and_validation/index.html
      index 9cdc102d..7fb28ae7 100644
      --- a/dev/concepts/advanced/typing_and_validation/index.html
      +++ b/dev/concepts/advanced/typing_and_validation/index.html
      @@ -1,4 +1,4 @@
      - Typing and validation - Django-Components      

      Typing and validation

      Adding type hints with GenericsΒ€

      New in version 0.92

      The Component class optionally accepts type parameters that allow you to specify the types of args, kwargs, slots, and data:

      class Button(Component[Args, Kwargs, Slots, Data, JsData, CssData]):
      + Typing and validation - Django-Components      

      Typing and validation

      Adding type hints with GenericsΒ€

      New in version 0.92

      The Component class optionally accepts type parameters that allow you to specify the types of args, kwargs, slots, and data:

      class Button(Component[Args, Kwargs, Slots, Data, JsData, CssData]):
           ...
       
      • Args - Must be a Tuple or Any
      • Kwargs - Must be a TypedDict or Any
      • Data - Must be a TypedDict or Any
      • Slots - Must be a TypedDict or Any

      Here's a full example:

      from typing import NotRequired, Tuple, TypedDict, SlotContent, SlotFunc
       
      diff --git a/dev/concepts/fundamentals/access_component_input/index.html b/dev/concepts/fundamentals/access_component_input/index.html
      index b1764ee7..d307ddd8 100644
      --- a/dev/concepts/fundamentals/access_component_input/index.html
      +++ b/dev/concepts/fundamentals/access_component_input/index.html
      @@ -1,4 +1,4 @@
      - Accessing component inputs - Django-Components     

      Accessing component inputs

      When you call Component.render or Component.render_to_response, the inputs to these methods can be accessed from within the instance under self.input.

      This means that you can use self.input inside:

      • get_context_data
      • get_template_name
      • get_template
      • on_render_before
      • on_render_after

      self.input is only defined during the execution of Component.render, and raises a RuntimeError when called outside of this context.

      self.input has the same fields as the input to Component.render:

      class TestComponent(Component):
      + Accessing component inputs - Django-Components     

      Accessing component inputs

      When you call Component.render or Component.render_to_response, the inputs to these methods can be accessed from within the instance under self.input.

      This means that you can use self.input inside:

      • get_context_data
      • get_template_name
      • get_template
      • on_render_before
      • on_render_after

      self.input is only defined during the execution of Component.render, and raises a RuntimeError when called outside of this context.

      self.input has the same fields as the input to Component.render:

      class TestComponent(Component):
           def get_context_data(self, var1, var2, variable, another, **attrs):
               assert self.input.args == (123, "str")
               assert self.input.kwargs == {"variable": "test", "another": 1}
      diff --git a/dev/concepts/fundamentals/autodiscovery/index.html b/dev/concepts/fundamentals/autodiscovery/index.html
      index 87afc566..9708a7d7 100644
      --- a/dev/concepts/fundamentals/autodiscovery/index.html
      +++ b/dev/concepts/fundamentals/autodiscovery/index.html
      @@ -1,4 +1,4 @@
      - Autodiscovery - Django-Components      

      Autodiscovery

      Every component that you want to use in the template with the {% component %} tag needs to be registered with the ComponentRegistry. Normally, we use the @register decorator for that:

      from django_components import Component, register
      + Autodiscovery - Django-Components      

      Autodiscovery

      Every component that you want to use in the template with the {% component %} tag needs to be registered with the ComponentRegistry. Normally, we use the @register decorator for that:

      from django_components import Component, register
       
       @register("calendar")
       class Calendar(Component):
      diff --git a/dev/concepts/fundamentals/component_context_scope/index.html b/dev/concepts/fundamentals/component_context_scope/index.html
      index 83062c83..fd83cd1d 100644
      --- a/dev/concepts/fundamentals/component_context_scope/index.html
      +++ b/dev/concepts/fundamentals/component_context_scope/index.html
      @@ -1,4 +1,4 @@
      - Component context and scope - Django-Components      

      Component context and scope

      By default, context variables are passed down the template as in regular Django - deeper scopes can access the variables from the outer scopes. So if you have several nested forloops, then inside the deep-most loop you can access variables defined by all previous loops.

      With this in mind, the {% component %} tag behaves similarly to {% include %} tag - inside the component tag, you can access all variables that were defined outside of it.

      And just like with {% include %}, if you don't want a specific component template to have access to the parent context, add only to the {% component %} tag:

      {% component "calendar" date="2015-06-19" only / %}
      + Component context and scope - Django-Components      

      Component context and scope

      By default, context variables are passed down the template as in regular Django - deeper scopes can access the variables from the outer scopes. So if you have several nested forloops, then inside the deep-most loop you can access variables defined by all previous loops.

      With this in mind, the {% component %} tag behaves similarly to {% include %} tag - inside the component tag, you can access all variables that were defined outside of it.

      And just like with {% include %}, if you don't want a specific component template to have access to the parent context, add only to the {% component %} tag:

      {% component "calendar" date="2015-06-19" only / %}
       

      NOTE: {% csrf_token %} tags need access to the top-level context, and they will not function properly if they are rendered in a component that is called with the only modifier.

      If you find yourself using the only modifier often, you can set the context_behavior option to "isolated", which automatically applies the only modifier. This is useful if you want to make sure that components don't accidentally access the outer context.

      Components can also access the outer context in their context methods like get_context_data by accessing the property self.outer_context.

      Example of Accessing Outer ContextΒ€

      <div>
         {% component "calender" / %}
       </div>
      diff --git a/dev/concepts/fundamentals/components_as_views/index.html b/dev/concepts/fundamentals/components_as_views/index.html
      index 47a1e25c..020dda13 100644
      --- a/dev/concepts/fundamentals/components_as_views/index.html
      +++ b/dev/concepts/fundamentals/components_as_views/index.html
      @@ -1,4 +1,4 @@
      - Components as views - Django-Components      

      Components as views

      New in version 0.34

      Note: Since 0.92, Component no longer subclasses View. To configure the View class, set the nested Component.View class

      Components can now be used as views:

      • Components define the Component.as_view() class method that can be used the same as View.as_view().

      • By default, you can define GET, POST or other HTTP handlers directly on the Component, same as you do with View. For example, you can override get and post to handle GET and POST requests, respectively.

      • In addition, Component now has a render_to_response method that renders the component template based on the provided context and slots' data and returns an HttpResponse object.

      Component as view exampleΒ€

      Here's an example of a calendar component defined as a view:

      # In a file called [project root]/components/calendar.py
      + Components as views - Django-Components      

      Components as views

      New in version 0.34

      Note: Since 0.92, Component no longer subclasses View. To configure the View class, set the nested Component.View class

      Components can now be used as views:

      • Components define the Component.as_view() class method that can be used the same as View.as_view().

      • By default, you can define GET, POST or other HTTP handlers directly on the Component, same as you do with View. For example, you can override get and post to handle GET and POST requests, respectively.

      • In addition, Component now has a render_to_response method that renders the component template based on the provided context and slots' data and returns an HttpResponse object.

      Component as view exampleΒ€

      Here's an example of a calendar component defined as a view:

      # In a file called [project root]/components/calendar.py
       from django_components import Component, ComponentView, register
       
       @register("calendar")
      diff --git a/dev/concepts/fundamentals/components_in_python/index.html b/dev/concepts/fundamentals/components_in_python/index.html
      index 3372b0bf..0969a60b 100644
      --- a/dev/concepts/fundamentals/components_in_python/index.html
      +++ b/dev/concepts/fundamentals/components_in_python/index.html
      @@ -1,4 +1,4 @@
      - Components in Python - Django-Components      

      Components in Python

      New in version 0.81

      Components can be rendered outside of Django templates, calling them as regular functions ("React-style").

      The component class defines render and render_to_response class methods. These methods accept positional args, kwargs, and slots, offering the same flexibility as the {% component %} tag:

      class SimpleComponent(Component):
      + Components in Python - Django-Components      

      Components in Python

      New in version 0.81

      Components can be rendered outside of Django templates, calling them as regular functions ("React-style").

      The component class defines render and render_to_response class methods. These methods accept positional args, kwargs, and slots, offering the same flexibility as the {% component %} tag:

      class SimpleComponent(Component):
           template = """
               {% load component_tags %}
               hello: {{ hello }}
      diff --git a/dev/concepts/fundamentals/components_in_templates/index.html b/dev/concepts/fundamentals/components_in_templates/index.html
      index b1f6bbc7..5c31bf32 100644
      --- a/dev/concepts/fundamentals/components_in_templates/index.html
      +++ b/dev/concepts/fundamentals/components_in_templates/index.html
      @@ -1,4 +1,4 @@
      - Components in templates - Django-Components     

      Components in templates

      First load the component_tags tag library, then use the component_[js/css]_dependencies and component tags to render the component to the page.

      {% load component_tags %}
      + Components in templates - Django-Components     

      Components in templates

      First load the component_tags tag library, then use the component_[js/css]_dependencies and component tags to render the component to the page.

      {% load component_tags %}
       <!DOCTYPE html>
       <html>
       <head>
      diff --git a/dev/concepts/fundamentals/defining_js_css_html_files/index.html b/dev/concepts/fundamentals/defining_js_css_html_files/index.html
      index b36fdc67..a10bf679 100644
      --- a/dev/concepts/fundamentals/defining_js_css_html_files/index.html
      +++ b/dev/concepts/fundamentals/defining_js_css_html_files/index.html
      @@ -1,4 +1,4 @@
      - Defining HTML / JS / CSS files - Django-Components      

      Defining HTML / JS / CSS files

      django_component's management of files builds on top of Django's Media class.

      To be familiar with how Django handles static files, we recommend reading also:

      Defining file paths relative to component or static dirsΒ€

      As seen in the getting started example, to associate HTML/JS/CSS files with a component, you set them as template_name, Media.js and Media.css respectively:

      # In a file [project root]/components/calendar/calendar.py
      + Defining HTML / JS / CSS files - Django-Components      

      Defining HTML / JS / CSS files

      django_component's management of files builds on top of Django's Media class.

      To be familiar with how Django handles static files, we recommend reading also:

      Defining file paths relative to component or static dirsΒ€

      As seen in the getting started example, to associate HTML/JS/CSS files with a component, you set them as template_name, Media.js and Media.css respectively:

      # In a file [project root]/components/calendar/calendar.py
       from django_components import Component, register
       
       @register("calendar")
      diff --git a/dev/concepts/fundamentals/html_attributes/index.html b/dev/concepts/fundamentals/html_attributes/index.html
      index 7bdbb115..28b79f90 100644
      --- a/dev/concepts/fundamentals/html_attributes/index.html
      +++ b/dev/concepts/fundamentals/html_attributes/index.html
      @@ -1,4 +1,4 @@
      - HTML attributes - Django-Components      

      HTML attributes

      New in version 0.74:

      You can use the html_attrs tag to render HTML attributes, given a dictionary of values.

      So if you have a template:

      <div class="{{ classes }}" data-id="{{ my_id }}">
      + HTML attributes - Django-Components      

      HTML attributes

      New in version 0.74:

      You can use the html_attrs tag to render HTML attributes, given a dictionary of values.

      So if you have a template:

      <div class="{{ classes }}" data-id="{{ my_id }}">
       </div>
       

      You can simplify it with html_attrs tag:

      <div {% html_attrs attrs %}>
       </div>
      diff --git a/dev/concepts/fundamentals/single_file_components/index.html b/dev/concepts/fundamentals/single_file_components/index.html
      index 8ea6d440..7f83977e 100644
      --- a/dev/concepts/fundamentals/single_file_components/index.html
      +++ b/dev/concepts/fundamentals/single_file_components/index.html
      @@ -1,4 +1,4 @@
      - Single-file components - Django-Components     

      Single-file components

      Components can also be defined in a single file, which is useful for small components. To do this, you can use the template, js, and css class attributes instead of the template_name and Media. For example, here's the calendar component from above, defined in a single file:

      [project root]/components/calendar.py
      # In a file called [project root]/components/calendar.py
      + Single-file components - Django-Components     

      Single-file components

      Components can also be defined in a single file, which is useful for small components. To do this, you can use the template, js, and css class attributes instead of the template_name and Media. For example, here's the calendar component from above, defined in a single file:

      [project root]/components/calendar.py
      # In a file called [project root]/components/calendar.py
       from django_components import Component, register, types
       
       @register("calendar")
      diff --git a/dev/concepts/fundamentals/slots/index.html b/dev/concepts/fundamentals/slots/index.html
      index 27510fba..df113255 100644
      --- a/dev/concepts/fundamentals/slots/index.html
      +++ b/dev/concepts/fundamentals/slots/index.html
      @@ -1,4 +1,4 @@
      - Slots - Django-Components      

      Slots

      New in version 0.26:

      • The slot tag now serves only to declare new slots inside the component template.
      • To override the content of a declared slot, use the newly introduced fill tag instead.
      • Whereas unfilled slots used to raise a warning, filling a slot is now optional by default.
      • To indicate that a slot must be filled, the new required option should be added at the end of the slot tag.

      Components support something called 'slots'. When a component is used inside another template, slots allow the parent template to override specific parts of the child component by passing in different content. This mechanism makes components more reusable and composable. This behavior is similar to slots in Vue.

      In the example below we introduce two block tags that work hand in hand to make this work. These are...

      • {% slot <name> %}/{% endslot %}: Declares a new slot in the component template.
      • {% fill <name> %}/{% endfill %}: (Used inside a {% component %} tag pair.) Fills a declared slot with the specified content.

      Let's update our calendar component to support more customization. We'll add slot tag pairs to its template, template.html.

      <div class="calendar-component">
      + Slots - Django-Components      

      Slots

      New in version 0.26:

      • The slot tag now serves only to declare new slots inside the component template.
      • To override the content of a declared slot, use the newly introduced fill tag instead.
      • Whereas unfilled slots used to raise a warning, filling a slot is now optional by default.
      • To indicate that a slot must be filled, the new required option should be added at the end of the slot tag.

      Components support something called 'slots'. When a component is used inside another template, slots allow the parent template to override specific parts of the child component by passing in different content. This mechanism makes components more reusable and composable. This behavior is similar to slots in Vue.

      In the example below we introduce two block tags that work hand in hand to make this work. These are...

      • {% slot <name> %}/{% endslot %}: Declares a new slot in the component template.
      • {% fill <name> %}/{% endfill %}: (Used inside a {% component %} tag pair.) Fills a declared slot with the specified content.

      Let's update our calendar component to support more customization. We'll add slot tag pairs to its template, template.html.

      <div class="calendar-component">
           <div class="header">
               {% slot "header" %}Calendar header{% endslot %}
           </div>
      diff --git a/dev/concepts/fundamentals/template_tag_syntax/index.html b/dev/concepts/fundamentals/template_tag_syntax/index.html
      index cee8d5d3..fb1e3d95 100644
      --- a/dev/concepts/fundamentals/template_tag_syntax/index.html
      +++ b/dev/concepts/fundamentals/template_tag_syntax/index.html
      @@ -1,4 +1,4 @@
      - Template tag syntax - Django-Components      

      Template tag syntax

      All template tags in django_component, like {% component %} or {% slot %}, and so on, support extra syntax that makes it possible to write components like in Vue or React (JSX).

      Self-closing tagsΒ€

      When you have a tag like {% component %} or {% slot %}, but it has no content, you can simply append a forward slash / at the end, instead of writing out the closing tags like {% endcomponent %} or {% endslot %}:

      So this:

      {% component "button" %}{% endcomponent %}
      + Template tag syntax - Django-Components      

      Template tag syntax

      All template tags in django_component, like {% component %} or {% slot %}, and so on, support extra syntax that makes it possible to write components like in Vue or React (JSX).

      Self-closing tagsΒ€

      When you have a tag like {% component %} or {% slot %}, but it has no content, you can simply append a forward slash / at the end, instead of writing out the closing tags like {% endcomponent %} or {% endslot %}:

      So this:

      {% component "button" %}{% endcomponent %}
       

      becomes

      {% component "button" / %}
       

      Special charactersΒ€

      New in version 0.71:

      Keyword arguments can contain special characters # @ . - _, so keywords like so are still valid:

      <body>
           {% component "calendar" my-date="2015-06-19" @click.native=do_something #some_id=True / %}
      diff --git a/dev/concepts/fundamentals/your_first_component/index.html b/dev/concepts/fundamentals/your_first_component/index.html
      index 788d298c..263c2816 100644
      --- a/dev/concepts/fundamentals/your_first_component/index.html
      +++ b/dev/concepts/fundamentals/your_first_component/index.html
      @@ -1,4 +1,4 @@
      - Create your first component - Django-Components     

      Create your first component

      A component in django-components is the combination of four things: CSS, Javascript, a Django template, and some Python code to put them all together.

          sampleproject/
      + Create your first component - Django-Components     

      Create your first component

      A component in django-components is the combination of four things: CSS, Javascript, a Django template, and some Python code to put them all together.

          sampleproject/
           β”œβ”€β”€ calendarapp/
           β”œβ”€β”€ components/             πŸ†•
           β”‚   └── calendar/           πŸ†•
      diff --git a/dev/devguides/dependency_mgmt/index.html b/dev/devguides/dependency_mgmt/index.html
      index 87bcc4a9..f990304e 100644
      --- a/dev/devguides/dependency_mgmt/index.html
      +++ b/dev/devguides/dependency_mgmt/index.html
      @@ -1,4 +1,4 @@
      - JS and CSS rendering - Django-Components      

      JS and CSS renderingΒ€

      Aim of this doc is to share the intuition on how we manage the JS and CSS ("dependencies") associated with components, and how we render them.

      Starting conditionsΒ€

      1. First of all, when we consider a component, it has two kind of dependencies - the "inlined" JS and CSS, and additional linked JS and CSS via Media.js/css:
      from django_components import Component, types
      + JS and CSS rendering - Django-Components      

      JS and CSS renderingΒ€

      Aim of this doc is to share the intuition on how we manage the JS and CSS ("dependencies") associated with components, and how we render them.

      Starting conditionsΒ€

      1. First of all, when we consider a component, it has two kind of dependencies - the "inlined" JS and CSS, and additional linked JS and CSS via Media.js/css:
      from django_components import Component, types
       
       class MyTable(Component):
           # Inlined JS
      diff --git a/dev/devguides/slot_rendering/index.html b/dev/devguides/slot_rendering/index.html
      index 4e88fb67..314ec2fc 100644
      --- a/dev/devguides/slot_rendering/index.html
      +++ b/dev/devguides/slot_rendering/index.html
      @@ -1,4 +1,4 @@
      - Slot rendering - Django-Components      

      Slot renderingΒ€

      This doc serves as a primer on how component slots and fills are resolved.

      FlowΒ€

      1. Imagine you have a template. Some kind of text, maybe HTML:

        | ------
        + Slot rendering - Django-Components      

        Slot renderingΒ€

        This doc serves as a primer on how component slots and fills are resolved.

        FlowΒ€

        1. Imagine you have a template. Some kind of text, maybe HTML:

          | ------
           | ---------
           | ----
           | -------
          diff --git a/dev/devguides/slots_and_blocks/index.html b/dev/devguides/slots_and_blocks/index.html
          index 6b114687..bc49492e 100644
          --- a/dev/devguides/slots_and_blocks/index.html
          +++ b/dev/devguides/slots_and_blocks/index.html
          @@ -1,4 +1,4 @@
          - Using slot and block tags - Django-Components      

          Using slot and block tagsΒ€

          1. First let's clarify how include and extends tags work inside components. So when component template includes include or extends tags, it's as if the "included" template was inlined. So if the "included" template contains slot tags, then the component uses those slots.

            So if you have a template `abc.html`:
            + Using slot and block tags - Django-Components      

            Using slot and block tagsΒ€

            1. First let's clarify how include and extends tags work inside components. So when component template includes include or extends tags, it's as if the "included" template was inlined. So if the "included" template contains slot tags, then the component uses those slots.

              So if you have a template `abc.html`:
               ```django
               <div>
                 hello
              diff --git a/dev/guides/setup/dev_server_setup/index.html b/dev/guides/setup/dev_server_setup/index.html
              index 3c6c5ae5..340be29c 100644
              --- a/dev/guides/setup/dev_server_setup/index.html
              +++ b/dev/guides/setup/dev_server_setup/index.html
              @@ -1 +1 @@
              - Running with development server - Django-Components      

              Running with development server

              Reload dev server on component file changesΒ€

              This is relevant if you are using the project structure as shown in our examples, where HTML, JS, CSS and Python are in separate files and nested in a directory.

              In this case you may notice that when you are running a development server, the server sometimes does not reload when you change component files.

              From relevant StackOverflow thread:

              TL;DR is that the server won't reload if it thinks the changed file is in a templates directory, or in a nested sub directory of a templates directory. This is by design.

              To make the dev server reload on all component files, set reload_on_file_change to True. This configures Django to watch for component files too.

              Note

              This setting should be enabled only for the dev environment!

              \ No newline at end of file + Running with development server - Django-Components

              Running with development server

              Reload dev server on component file changesΒ€

              This is relevant if you are using the project structure as shown in our examples, where HTML, JS, CSS and Python are in separate files and nested in a directory.

              In this case you may notice that when you are running a development server, the server sometimes does not reload when you change component files.

              From relevant StackOverflow thread:

              TL;DR is that the server won't reload if it thinks the changed file is in a templates directory, or in a nested sub directory of a templates directory. This is by design.

              To make the dev server reload on all component files, set reload_on_file_change to True. This configures Django to watch for component files too.

              Note

              This setting should be enabled only for the dev environment!

              \ No newline at end of file diff --git a/dev/guides/setup/logging_and_debugging/index.html b/dev/guides/setup/logging_and_debugging/index.html index c018f384..98925a08 100644 --- a/dev/guides/setup/logging_and_debugging/index.html +++ b/dev/guides/setup/logging_and_debugging/index.html @@ -1,4 +1,4 @@ - Logging and debugging - Django-Components

              Logging and debugging

              Django components supports logging with Django. This can help with troubleshooting.

              To configure logging for Django components, set the django_components logger in LOGGING in settings.py (below).

              Also see the settings.py file in sampleproject for a real-life example.

              import logging
              + Logging and debugging - Django-Components     

              Logging and debugging

              Django components supports logging with Django. This can help with troubleshooting.

              To configure logging for Django components, set the django_components logger in LOGGING in settings.py (below).

              Also see the settings.py file in sampleproject for a real-life example.

              import logging
               import sys
               
               LOGGING = {
              diff --git a/dev/guides/setup/syntax_highlight/index.html b/dev/guides/setup/syntax_highlight/index.html
              index e11d2b36..27357eb2 100644
              --- a/dev/guides/setup/syntax_highlight/index.html
              +++ b/dev/guides/setup/syntax_highlight/index.html
              @@ -1,4 +1,4 @@
              - Syntax highlighting - Django-Components      

              Syntax highlighting

              VSCodeΒ€

              Note, in the above example, that the t.django_html, t.css, and t.js types are used to specify the type of the template, CSS, and JS files, respectively. This is not necessary, but if you're using VSCode with the Python Inline Source Syntax Highlighting extension, it will give you syntax highlighting for the template, CSS, and JS.

              Pycharm (or other Jetbrains IDEs)Β€

              If you're a Pycharm user (or any other editor from Jetbrains), you can have coding assistance as well:

              from django_components import Component, register
              + Syntax highlighting - Django-Components      

              Syntax highlighting

              VSCodeΒ€

              Note, in the above example, that the t.django_html, t.css, and t.js types are used to specify the type of the template, CSS, and JS files, respectively. This is not necessary, but if you're using VSCode with the Python Inline Source Syntax Highlighting extension, it will give you syntax highlighting for the template, CSS, and JS.

              Pycharm (or other Jetbrains IDEs)Β€

              If you're a Pycharm user (or any other editor from Jetbrains), you can have coding assistance as well:

              from django_components import Component, register
               
               @register("calendar")
               class Calendar(Component):
              diff --git a/dev/index.html b/dev/index.html
              index c4483665..0a151c41 100644
              --- a/dev/index.html
              +++ b/dev/index.html
              @@ -1,4 +1,4 @@
              - Welcome to Django Components - Django-Components      

              Welcome to Django Components


              django-components

              PyPI - Version PyPI - Python Version PyPI - License PyPI - Downloads GitHub Actions Workflow Status

              django-components introduces component-based architecture to Django's server-side rendering. It combines Django's templating system with the modularity seen in modern frontend frameworks like Vue or React.

              FeaturesΒ€

              1. 🧩 Reusability: Allows creation of self-contained, reusable UI elements.
              2. πŸ“¦ Encapsulation: Each component can include its own HTML, CSS, and JavaScript.
              3. πŸš€ Server-side rendering: Components render on the server, improving initial load times and SEO.
              4. 🐍 Django integration: Works within the Django ecosystem, using familiar concepts like template tags.
              5. ⚑ Asynchronous loading: Components can render independently opening up for integration with JS frameworks like HTMX or AlpineJS.

              Potential benefits:

              • πŸ”„ Reduced code duplication
              • πŸ› οΈ Improved maintainability through modular design
              • 🧠 Easier management of complex UIs
              • 🀝 Enhanced collaboration between frontend and backend developers

              Django-components can be particularly useful for larger Django projects that require a more structured approach to UI development, without necessitating a shift to a separate frontend framework.

              QuickstartΒ€

              django-components lets you create reusable blocks of code needed to generate the front end code you need for a modern app.

              Define a component in components/calendar/calendar.py like this:

              @register("calendar")
              + Welcome to Django Components - Django-Components      

              Welcome to Django Components


              django-components

              PyPI - Version PyPI - Python Version PyPI - License PyPI - Downloads GitHub Actions Workflow Status

              django-components introduces component-based architecture to Django's server-side rendering. It combines Django's templating system with the modularity seen in modern frontend frameworks like Vue or React.

              FeaturesΒ€

              1. 🧩 Reusability: Allows creation of self-contained, reusable UI elements.
              2. πŸ“¦ Encapsulation: Each component can include its own HTML, CSS, and JavaScript.
              3. πŸš€ Server-side rendering: Components render on the server, improving initial load times and SEO.
              4. 🐍 Django integration: Works within the Django ecosystem, using familiar concepts like template tags.
              5. ⚑ Asynchronous loading: Components can render independently opening up for integration with JS frameworks like HTMX or AlpineJS.

              Potential benefits:

              • πŸ”„ Reduced code duplication
              • πŸ› οΈ Improved maintainability through modular design
              • 🧠 Easier management of complex UIs
              • 🀝 Enhanced collaboration between frontend and backend developers

              Django-components can be particularly useful for larger Django projects that require a more structured approach to UI development, without necessitating a shift to a separate frontend framework.

              QuickstartΒ€

              django-components lets you create reusable blocks of code needed to generate the front end code you need for a modern app.

              Define a component in components/calendar/calendar.py like this:

              @register("calendar")
               class Calendar(Component):
                   template_name = "template.html"
               
              @@ -7,4 +7,4 @@
               

              With this template.html file:

              <div class="calendar-component">Today's date is <span>{{ date }}</span></div>
               

              Use the component like this:

              {% component "calendar" date="2024-11-06" %}{% endcomponent %}
               

              And this is what gets rendered:

              <div class="calendar-component">Today's date is <span>2024-11-06</span></div>
              -

              Read on to learn about all the exciting details and configuration possibilities!

              (If you instead prefer to jump right into the code, check out the example project)

              Release notesΒ€

              Read the Release Notes to see the latest features and fixes.

              Community examplesΒ€

              One of our goals with django-components is to make it easy to share components between projects. If you have a set of components that you think would be useful to others, please open a pull request to add them to the list below.

              \ No newline at end of file +

              Read on to learn about all the exciting details and configuration possibilities!

              (If you instead prefer to jump right into the code, check out the example project)

              Release notesΒ€

              Read the Release Notes to see the latest features and fixes.

              Community examplesΒ€

              One of our goals with django-components is to make it easy to share components between projects. If you have a set of components that you think would be useful to others, please open a pull request to add them to the list below.

              \ No newline at end of file diff --git a/dev/migrating_from_safer_staticfiles/index.html b/dev/migrating_from_safer_staticfiles/index.html index facd5b0b..d1e3f5b6 100644 --- a/dev/migrating_from_safer_staticfiles/index.html +++ b/dev/migrating_from_safer_staticfiles/index.html @@ -1,4 +1,4 @@ - Migrating from safer_staticfiles - Django-Components

              Migrating from safer_staticfilesΒ€

              This guide is for you if you're upgrating django_components to v0.100 or later from older versions.

              In version 0.100, we changed how components' static JS and CSS files are handled. See more in the "Static files" section.

              Migration steps:

              1. Remove django_components.safer_staticfiles from INSTALLED_APPS in your settings.py, and replace it with django.contrib.staticfiles.

              Before:

              INSTALLED_APPS = [
              + Migrating from safer_staticfiles - Django-Components      

              Migrating from safer_staticfilesΒ€

              This guide is for you if you're upgrating django_components to v0.100 or later from older versions.

              In version 0.100, we changed how components' static JS and CSS files are handled. See more in the "Static files" section.

              Migration steps:

              1. Remove django_components.safer_staticfiles from INSTALLED_APPS in your settings.py, and replace it with django.contrib.staticfiles.

              Before:

              INSTALLED_APPS = [
                  "django.contrib.admin",
                  ...
                  # "django.contrib.staticfiles",  # <-- ADD
              diff --git a/dev/overview/code_of_conduct/index.html b/dev/overview/code_of_conduct/index.html
              index 150e3fdd..04363b3d 100644
              --- a/dev/overview/code_of_conduct/index.html
              +++ b/dev/overview/code_of_conduct/index.html
              @@ -1 +1 @@
              - Code of Conduct - Django-Components      

              Contributor Covenant Code of ConductΒ€

              Our PledgeΒ€

              In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

              Our StandardsΒ€

              Examples of behavior that contributes to creating a positive environment include:

              • Using welcoming and inclusive language
              • Being respectful of differing viewpoints and experiences
              • Gracefully accepting constructive criticism
              • Focusing on what is best for the community
              • Showing empathy towards other community members

              Examples of unacceptable behavior by participants include:

              • The use of sexualized language or imagery and unwelcome sexual attention or advances
              • Trolling, insulting/derogatory comments, and personal or political attacks
              • Public or private harassment
              • Publishing others' private information, such as a physical or electronic address, without explicit permission
              • Other conduct which could reasonably be considered inappropriate in a professional setting

              Our ResponsibilitiesΒ€

              Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

              Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

              ScopeΒ€

              This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

              EnforcementΒ€

              Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at emil@emilstenstrom.se. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

              Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

              AttributionΒ€

              This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

              For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq

              \ No newline at end of file + Code of Conduct - Django-Components

              Contributor Covenant Code of ConductΒ€

              Our PledgeΒ€

              In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

              Our StandardsΒ€

              Examples of behavior that contributes to creating a positive environment include:

              • Using welcoming and inclusive language
              • Being respectful of differing viewpoints and experiences
              • Gracefully accepting constructive criticism
              • Focusing on what is best for the community
              • Showing empathy towards other community members

              Examples of unacceptable behavior by participants include:

              • The use of sexualized language or imagery and unwelcome sexual attention or advances
              • Trolling, insulting/derogatory comments, and personal or political attacks
              • Public or private harassment
              • Publishing others' private information, such as a physical or electronic address, without explicit permission
              • Other conduct which could reasonably be considered inappropriate in a professional setting

              Our ResponsibilitiesΒ€

              Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

              Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

              ScopeΒ€

              This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

              EnforcementΒ€

              Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at emil@emilstenstrom.se. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

              Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

              AttributionΒ€

              This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

              For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq

              \ No newline at end of file diff --git a/dev/overview/community/index.html b/dev/overview/community/index.html index 4468ffc3..cede2d44 100644 --- a/dev/overview/community/index.html +++ b/dev/overview/community/index.html @@ -1 +1 @@ - Community - Django-Components

              Community

              Community questionsΒ€

              The best place to ask questions is in our Github Discussion board.

              Please, before opening a new discussion, check if similar discussion wasn't opened already.

              Community examplesΒ€

              One of our goals with django-components is to make it easy to share components between projects. If you have a set of components that you think would be useful to others, please open a pull request to add them to the list below.

              \ No newline at end of file + Community - Django-Components

              Community

              Community questionsΒ€

              The best place to ask questions is in our Github Discussion board.

              Please, before opening a new discussion, check if similar discussion wasn't opened already.

              Community examplesΒ€

              One of our goals with django-components is to make it easy to share components between projects. If you have a set of components that you think would be useful to others, please open a pull request to add them to the list below.

              \ No newline at end of file diff --git a/dev/overview/compatibility/index.html b/dev/overview/compatibility/index.html index 6fe4c7f5..41323d9b 100644 --- a/dev/overview/compatibility/index.html +++ b/dev/overview/compatibility/index.html @@ -1 +1 @@ - Compatibility - Django-Components

              Compatibility

              CompatibilityΒ€

              Django-components supports all supported combinations versions of Django and Python.

              Python version Django version
              3.8 4.2
              3.9 4.2
              3.10 4.2, 5.0, 5.1
              3.11 4.2, 5.0, 5.1
              3.12 4.2, 5.0, 5.1
              3.13 5.1
              \ No newline at end of file + Compatibility - Django-Components

              Compatibility

              CompatibilityΒ€

              Django-components supports all supported combinations versions of Django and Python.

              Python version Django version
              3.8 4.2
              3.9 4.2
              3.10 4.2, 5.0, 5.1
              3.11 4.2, 5.0, 5.1
              3.12 4.2, 5.0, 5.1
              3.13 5.1
              \ No newline at end of file diff --git a/dev/overview/contributing/index.html b/dev/overview/contributing/index.html index 9a69869f..538d743c 100644 --- a/dev/overview/contributing/index.html +++ b/dev/overview/contributing/index.html @@ -1 +1 @@ - Contributing - Django-Components

              Contributing

              Bug reportsΒ€

              If you find a bug, please open an issue with detailed description of what happened.

              Bug fixesΒ€

              If you found a fix for a bug or typo, go ahead and open a PR with a fix. We'll help you out with the rest!

              Feature requestsΒ€

              For feature requests or suggestions, please open either a discussion or an issue.

              Getting involvedΒ€

              django_components is still under active development, and there's much to build, so come aboard!

              SponsoringΒ€

              Another way you can get involved is by donating to the development of django_components.

              \ No newline at end of file + Contributing - Django-Components

              Contributing

              Bug reportsΒ€

              If you find a bug, please open an issue with detailed description of what happened.

              Bug fixesΒ€

              If you found a fix for a bug or typo, go ahead and open a PR with a fix. We'll help you out with the rest!

              Feature requestsΒ€

              For feature requests or suggestions, please open either a discussion or an issue.

              Getting involvedΒ€

              django_components is still under active development, and there's much to build, so come aboard!

              SponsoringΒ€

              Another way you can get involved is by donating to the development of django_components.

              \ No newline at end of file diff --git a/dev/overview/development/index.html b/dev/overview/development/index.html index 41eade3e..a9d4c339 100644 --- a/dev/overview/development/index.html +++ b/dev/overview/development/index.html @@ -1,4 +1,4 @@ - Development - Django-Components

              Development

              Install locally and run the testsΒ€

              Start by forking the project by clicking the Fork button up in the right corner in the GitHub . This makes a copy of the repository in your own name. Now you can clone this repository locally and start adding features:

              git clone https://github.com/<your GitHub username>/django-components.git
              + Development - Django-Components      

              Development

              Install locally and run the testsΒ€

              Start by forking the project by clicking the Fork button up in the right corner in the GitHub . This makes a copy of the repository in your own name. Now you can clone this repository locally and start adding features:

              git clone https://github.com/<your GitHub username>/django-components.git
               

              To quickly run the tests install the local dependencies by running:

              pip install -r requirements-dev.txt
               

              Now you can run the tests to make sure everything works as expected:

              pytest
               

              The library is also tested across many versions of Python and Django. To run tests that way:

              pyenv install -s 3.8
              diff --git a/dev/overview/installation/index.html b/dev/overview/installation/index.html
              index 189bcc09..089a603a 100644
              --- a/dev/overview/installation/index.html
              +++ b/dev/overview/installation/index.html
              @@ -1,4 +1,4 @@
              - Installation - Django-Components      

              Installation

              1. Install django_components into your environment:

                pip install django_components
                + Installation - Django-Components      

                Installation

                1. Install django_components into your environment:

                  pip install django_components
                   
                2. Load django_components into Django by adding it into INSTALLED_APPS in settings.py:

                  INSTALLED_APPS = [
                       ...,
                       'django_components',
                  diff --git a/dev/overview/license/index.html b/dev/overview/license/index.html
                  index 31ad6a11..1122b8ee 100644
                  --- a/dev/overview/license/index.html
                  +++ b/dev/overview/license/index.html
                  @@ -1 +1 @@
                  - License - Django-Components     

                  License

                  MIT License

                  Copyright (c) 2019 Emil StenstrΓΆm

                  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

                  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

                  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

                  \ No newline at end of file + License - Django-Components

                  License

                  MIT License

                  Copyright (c) 2019 Emil StenstrΓΆm

                  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

                  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

                  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

                  \ No newline at end of file diff --git a/dev/overview/security_notes/index.html b/dev/overview/security_notes/index.html index 3460657e..96e8fe90 100644 --- a/dev/overview/security_notes/index.html +++ b/dev/overview/security_notes/index.html @@ -1,4 +1,4 @@ - Security notes 🚨 - Django-Components

                  Security notes 🚨

                  It is strongly recommended to read this section before using django-components in production.

                  Static filesΒ€

                  Components can be organized however you prefer. That said, our prefered way is to keep the files of a component close together by bundling them in the same directory.

                  This means that files containing backend logic, such as Python modules and HTML templates, live in the same directory as static files, e.g. JS and CSS.

                  From v0.100 onwards, we keep component files (as defined by COMPONENTS.dirs and COMPONENTS.app_dirs) separate from the rest of the static files (defined by STATICFILES_DIRS). That way, the Python and HTML files are NOT exposed by the server. Only the static JS, CSS, and other common formats.

                  NOTE: If you need to expose different file formats, you can configure these with COMPONENTS.static_files_allowed and COMPONENTS.static_files_forbidden.

                  Static files prior to v0.100Β€

                  Prior to v0.100, if your were using django.contrib.staticfiles to collect static files, no distinction was made between the different kinds of files.

                  As a result, your Python code and templates may inadvertently become available on your static file server. You probably don't want this, as parts of your backend logic will be exposed, posing a potential security vulnerability.

                  From v0.27 until v0.100, django-components shipped with an additional installable app django_components.safer_staticfiles. It was a drop-in replacement for django.contrib.staticfiles. Its behavior is 100% identical except it ignores .py and .html files, meaning these will not end up on your static files server. To use it, add it to INSTALLED_APPS and remove django.contrib.staticfiles.

                  INSTALLED_APPS = [
                  + Security notes 🚨 - Django-Components      

                  Security notes 🚨

                  It is strongly recommended to read this section before using django-components in production.

                  Static filesΒ€

                  Components can be organized however you prefer. That said, our prefered way is to keep the files of a component close together by bundling them in the same directory.

                  This means that files containing backend logic, such as Python modules and HTML templates, live in the same directory as static files, e.g. JS and CSS.

                  From v0.100 onwards, we keep component files (as defined by COMPONENTS.dirs and COMPONENTS.app_dirs) separate from the rest of the static files (defined by STATICFILES_DIRS). That way, the Python and HTML files are NOT exposed by the server. Only the static JS, CSS, and other common formats.

                  NOTE: If you need to expose different file formats, you can configure these with COMPONENTS.static_files_allowed and COMPONENTS.static_files_forbidden.

                  Static files prior to v0.100Β€

                  Prior to v0.100, if your were using django.contrib.staticfiles to collect static files, no distinction was made between the different kinds of files.

                  As a result, your Python code and templates may inadvertently become available on your static file server. You probably don't want this, as parts of your backend logic will be exposed, posing a potential security vulnerability.

                  From v0.27 until v0.100, django-components shipped with an additional installable app django_components.safer_staticfiles. It was a drop-in replacement for django.contrib.staticfiles. Its behavior is 100% identical except it ignores .py and .html files, meaning these will not end up on your static files server. To use it, add it to INSTALLED_APPS and remove django.contrib.staticfiles.

                  INSTALLED_APPS = [
                       # 'django.contrib.staticfiles',   # <-- REMOVE
                       'django_components',
                       'django_components.safer_staticfiles'  # <-- ADD
                  diff --git a/dev/overview/welcome/index.html b/dev/overview/welcome/index.html
                  index dcf36107..a695b945 100644
                  --- a/dev/overview/welcome/index.html
                  +++ b/dev/overview/welcome/index.html
                  @@ -1,4 +1,4 @@
                  - Welcome to Django Components - Django-Components      

                  Welcome to Django Components

                  django-components

                  PyPI - Version PyPI - Python Version PyPI - License PyPI - Downloads GitHub Actions Workflow Status

                  django-components introduces component-based architecture to Django's server-side rendering. It combines Django's templating system with the modularity seen in modern frontend frameworks like Vue or React.

                  FeaturesΒ€

                  1. 🧩 Reusability: Allows creation of self-contained, reusable UI elements.
                  2. πŸ“¦ Encapsulation: Each component can include its own HTML, CSS, and JavaScript.
                  3. πŸš€ Server-side rendering: Components render on the server, improving initial load times and SEO.
                  4. 🐍 Django integration: Works within the Django ecosystem, using familiar concepts like template tags.
                  5. ⚑ Asynchronous loading: Components can render independently opening up for integration with JS frameworks like HTMX or AlpineJS.

                  Potential benefits:

                  • πŸ”„ Reduced code duplication
                  • πŸ› οΈ Improved maintainability through modular design
                  • 🧠 Easier management of complex UIs
                  • 🀝 Enhanced collaboration between frontend and backend developers

                  Django-components can be particularly useful for larger Django projects that require a more structured approach to UI development, without necessitating a shift to a separate frontend framework.

                  QuickstartΒ€

                  django-components lets you create reusable blocks of code needed to generate the front end code you need for a modern app.

                  Define a component in components/calendar/calendar.py like this:

                  @register("calendar")
                  + Welcome to Django Components - Django-Components      

                  Welcome to Django Components

                  django-components

                  PyPI - Version PyPI - Python Version PyPI - License PyPI - Downloads GitHub Actions Workflow Status

                  django-components introduces component-based architecture to Django's server-side rendering. It combines Django's templating system with the modularity seen in modern frontend frameworks like Vue or React.

                  FeaturesΒ€

                  1. 🧩 Reusability: Allows creation of self-contained, reusable UI elements.
                  2. πŸ“¦ Encapsulation: Each component can include its own HTML, CSS, and JavaScript.
                  3. πŸš€ Server-side rendering: Components render on the server, improving initial load times and SEO.
                  4. 🐍 Django integration: Works within the Django ecosystem, using familiar concepts like template tags.
                  5. ⚑ Asynchronous loading: Components can render independently opening up for integration with JS frameworks like HTMX or AlpineJS.

                  Potential benefits:

                  • πŸ”„ Reduced code duplication
                  • πŸ› οΈ Improved maintainability through modular design
                  • 🧠 Easier management of complex UIs
                  • 🀝 Enhanced collaboration between frontend and backend developers

                  Django-components can be particularly useful for larger Django projects that require a more structured approach to UI development, without necessitating a shift to a separate frontend framework.

                  QuickstartΒ€

                  django-components lets you create reusable blocks of code needed to generate the front end code you need for a modern app.

                  Define a component in components/calendar/calendar.py like this:

                  @register("calendar")
                   class Calendar(Component):
                       template_name = "template.html"
                   
                  diff --git a/dev/reference/api/index.html b/dev/reference/api/index.html
                  index 446de0ad..07c01ea5 100644
                  --- a/dev/reference/api/index.html
                  +++ b/dev/reference/api/index.html
                  @@ -1,4 +1,4 @@
                  - Api - Django-Components      

                  APIΒ€

                  Component Β€

                  Component(
                  + Api - Django-Components      

                  APIΒ€

                  Component Β€

                  Component(
                       registered_name: Optional[str] = None,
                       component_id: Optional[str] = None,
                       outer_context: Optional[Context] = None,
                  diff --git a/dev/reference/commands/index.html b/dev/reference/commands/index.html
                  index e4579947..b176a43a 100644
                  --- a/dev/reference/commands/index.html
                  +++ b/dev/reference/commands/index.html
                  @@ -1,4 +1,4 @@
                  - Commands - Django-Components      

                  CommandsΒ€

                  These are all the Django management commands that will be added by installing django_components:

                  startcomponentΒ€

                  usage: manage.py startcomponent [-h] [--path PATH] [--js JS] [--css CSS]
                  + Commands - Django-Components      

                  CommandsΒ€

                  These are all the Django management commands that will be added by installing django_components:

                  startcomponentΒ€

                  usage: manage.py startcomponent [-h] [--path PATH] [--js JS] [--css CSS]
                                                   [--template TEMPLATE] [--force] [--verbose]
                                                   [--dry-run] [--version] [-v {0,1,2,3}]
                                                   [--settings SETTINGS]
                  diff --git a/dev/reference/components/index.html b/dev/reference/components/index.html
                  index b5fa3465..bae6f81b 100644
                  --- a/dev/reference/components/index.html
                  +++ b/dev/reference/components/index.html
                  @@ -1,4 +1,4 @@
                  - Components - Django-Components      

                  ComponentsΒ€

                  These are the components provided by django_components.

                  DynamicComponent Β€

                  Bases: django_components.component.Component

                  See source code

                  This component is given a registered name or a reference to another component, and behaves as if the other component was in its place.

                  The args, kwargs, and slot fills are all passed down to the underlying component.

                  Parameters:

                  • is (str | Type[Component]) –

                    Component that should be rendered. Either a registered name of a component, or a Component class directly. Required.

                  • registry (ComponentRegistry, default: None ) –

                    Specify the registry to search for the registered name. If omitted, all registries are searched until the first match.

                  • *args –

                    Additional data passed to the component.

                  • **kwargs –

                    Additional data passed to the component.

                  Slots:

                  • Any slots, depending on the actual component.

                  Examples:

                  Django

                  {% component "dynamic" is=table_comp data=table_data headers=table_headers %}
                  + Components - Django-Components      

                  ComponentsΒ€

                  These are the components provided by django_components.

                  DynamicComponent Β€

                  Bases: django_components.component.Component

                  See source code

                  This component is given a registered name or a reference to another component, and behaves as if the other component was in its place.

                  The args, kwargs, and slot fills are all passed down to the underlying component.

                  Parameters:

                  • is (str | Type[Component]) –

                    Component that should be rendered. Either a registered name of a component, or a Component class directly. Required.

                  • registry (ComponentRegistry, default: None ) –

                    Specify the registry to search for the registered name. If omitted, all registries are searched until the first match.

                  • *args –

                    Additional data passed to the component.

                  • **kwargs –

                    Additional data passed to the component.

                  Slots:

                  • Any slots, depending on the actual component.

                  Examples:

                  Django

                  {% component "dynamic" is=table_comp data=table_data headers=table_headers %}
                       {% fill "pagination" %}
                           {% component "pagination" / %}
                       {% endfill %}
                  diff --git a/dev/reference/exceptions/index.html b/dev/reference/exceptions/index.html
                  index b0ae340b..8dc9ad61 100644
                  --- a/dev/reference/exceptions/index.html
                  +++ b/dev/reference/exceptions/index.html
                  @@ -1,3 +1,3 @@
                  - Exceptions - Django-Components      

                  ExceptionsΒ€

                  AlreadyRegistered Β€

                  Bases: Exception

                  See source code

                  Raised when you try to register a Component, but it's already registered with given ComponentRegistry.

                  NotRegistered Β€

                  Bases: Exception

                  See source code

                  Raised when you try to access a Component, but it's NOT registered with given ComponentRegistry.

                  TagProtectedError Β€

                  Bases: Exception

                  See source code

                  The way the TagFormatter works is that, based on which start and end tags are used for rendering components, the ComponentRegistry behind the scenes un-/registers the template tags with the associated instance of Django's Library.

                  In other words, if I have registered a component "table", and I use the shorthand syntax:

                  {% table ... %}
                  + Exceptions - Django-Components      

                  ExceptionsΒ€

                  AlreadyRegistered Β€

                  Bases: Exception

                  See source code

                  Raised when you try to register a Component, but it's already registered with given ComponentRegistry.

                  NotRegistered Β€

                  Bases: Exception

                  See source code

                  Raised when you try to access a Component, but it's NOT registered with given ComponentRegistry.

                  TagProtectedError Β€

                  Bases: Exception

                  See source code

                  The way the TagFormatter works is that, based on which start and end tags are used for rendering components, the ComponentRegistry behind the scenes un-/registers the template tags with the associated instance of Django's Library.

                  In other words, if I have registered a component "table", and I use the shorthand syntax:

                  {% table ... %}
                   {% endtable %}
                   

                  Then ComponentRegistry registers the tag table onto the Django's Library instance.

                  However, that means that if we registered a component "slot", then we would overwrite the {% slot %} tag from django_components.

                  Thus, this exception is raised when a component is attempted to be registered under a forbidden name, such that it would overwrite one of django_component's own template tags.

                  \ No newline at end of file diff --git a/dev/reference/middlewares/index.html b/dev/reference/middlewares/index.html index 22f0db60..77395aff 100644 --- a/dev/reference/middlewares/index.html +++ b/dev/reference/middlewares/index.html @@ -1 +1 @@ - Middlewares - Django-Components
                  \ No newline at end of file + Middlewares - Django-Components
                  \ No newline at end of file diff --git a/dev/reference/settings/index.html b/dev/reference/settings/index.html index 0114da21..b3bd4e9d 100644 --- a/dev/reference/settings/index.html +++ b/dev/reference/settings/index.html @@ -1,4 +1,4 @@ - Settings - Django-Components

                  SettingsΒ€

                  You can configure django_components with a global COMPONENTS variable in your Django settings file, e.g. settings.py. By default you don't need it set, there are resonable defaults.

                  To configure the settings you can instantiate ComponentsSettings for validation and type hints. Or, for backwards compatibility, you can also use plain dictionary:

                  # settings.py
                  + Settings - Django-Components      

                  SettingsΒ€

                  You can configure django_components with a global COMPONENTS variable in your Django settings file, e.g. settings.py. By default you don't need it set, there are resonable defaults.

                  To configure the settings you can instantiate ComponentsSettings for validation and type hints. Or, for backwards compatibility, you can also use plain dictionary:

                  # settings.py
                   from django_components import ComponentsSettings
                   
                   COMPONENTS = ComponentsSettings(
                  diff --git a/dev/reference/tag_formatters/index.html b/dev/reference/tag_formatters/index.html
                  index d85d5697..76e09f72 100644
                  --- a/dev/reference/tag_formatters/index.html
                  +++ b/dev/reference/tag_formatters/index.html
                  @@ -1,4 +1,4 @@
                  - Tag formatters - Django-Components      

                  Tag FormattersΒ€

                  Tag formatters allow you to change the syntax for calling components from within the Django templates.

                  Tag formatter are set via the tag_formatter setting.

                  Available tag formattersΒ€

                  ComponentFormatter Β€

                  Bases: django_components.tag_formatter.TagFormatterABC

                  See source code

                  The original django_component's component tag formatter, it uses the {% component %} and {% endcomponent %} tags, and the component name is given as the first positional arg.

                  Example as block:

                  {% component "mycomp" abc=123 %}
                  + Tag formatters - Django-Components      

                  Tag FormattersΒ€

                  Tag formatters allow you to change the syntax for calling components from within the Django templates.

                  Tag formatter are set via the tag_formatter setting.

                  Available tag formattersΒ€

                  ComponentFormatter Β€

                  Bases: django_components.tag_formatter.TagFormatterABC

                  See source code

                  The original django_component's component tag formatter, it uses the {% component %} and {% endcomponent %} tags, and the component name is given as the first positional arg.

                  Example as block:

                  {% component "mycomp" abc=123 %}
                       {% fill "myfill" %}
                           ...
                       {% endfill %}
                  diff --git a/dev/reference/template_tags/index.html b/dev/reference/template_tags/index.html
                  index d445bf41..ca4d03f9 100644
                  --- a/dev/reference/template_tags/index.html
                  +++ b/dev/reference/template_tags/index.html
                  @@ -1,4 +1,4 @@
                  - Template tags - Django-Components      

                  Template tagsΒ€

                  All following template tags are defined in

                  django_components.templatetags.component_tags

                  Import as

                  {% load component_tags %}
                  + Template tags - Django-Components      

                  Template tagsΒ€

                  All following template tags are defined in

                  django_components.templatetags.component_tags

                  Import as

                  {% load component_tags %}
                   

                  componentΒ€

                  {% component [arg, ...] **kwargs [only] %}
                   {% endcomponent %}
                   

                  See source code

                  Renders one of the components that was previously registered with @register() decorator.

                  Args:

                  • name (str, required): Registered name of the component to render
                  • All other args and kwargs are defined based on the component itself.

                  If you defined a component "my_table"

                  from django_component import Component, register
                  diff --git a/dev/reference/template_vars/index.html b/dev/reference/template_vars/index.html
                  index 5a321634..3e671728 100644
                  --- a/dev/reference/template_vars/index.html
                  +++ b/dev/reference/template_vars/index.html
                  @@ -1,4 +1,4 @@
                  - Template vars - Django-Components      

                  Template variablesΒ€

                  Here is a list of all variables that are automatically available from inside the component's template and in on_render_before / on_render_after hooks.

                  is_filled instance-attribute Β€

                  is_filled: Dict[str, bool]
                  + Template vars - Django-Components      

                  Template variablesΒ€

                  Here is a list of all variables that are automatically available from inside the component's template and in on_render_before / on_render_after hooks.

                  is_filled instance-attribute Β€

                  is_filled: Dict[str, bool]
                   

                  See source code

                  Dictonary describing which component slots are filled (True) or are not (False).

                  New in version 0.70

                  Use as {{ component_vars.is_filled }}

                  Example:

                  {# Render wrapping HTML only if the slot is defined #}
                   {% if component_vars.is_filled.my_slot %}
                       <div class="slot-wrapper">
                  diff --git a/dev/reference/urls/index.html b/dev/reference/urls/index.html
                  index c8d0c866..e97a6d43 100644
                  --- a/dev/reference/urls/index.html
                  +++ b/dev/reference/urls/index.html
                  @@ -1,4 +1,4 @@
                  - Urls - Django-Components      

                  URLsΒ€

                  Below are all the URL patterns that will be added by adding django_components.urls.

                  See Installation on how to add these URLs to your Django project.

                  Django components already prefixes all URLs with components/. So when you are adding the URLs to urlpatterns, you can use an empty string as the first argument:

                  from django.urls import include, path
                  + Urls - Django-Components      

                  URLsΒ€

                  Below are all the URL patterns that will be added by adding django_components.urls.

                  See Installation on how to add these URLs to your Django project.

                  Django components already prefixes all URLs with components/. So when you are adding the URLs to urlpatterns, you can use an empty string as the first argument:

                  from django.urls import include, path
                   
                   urlpatterns = [
                       ...
                  diff --git a/dev/release_notes/index.html b/dev/release_notes/index.html
                  index 505fd3cf..84450220 100644
                  --- a/dev/release_notes/index.html
                  +++ b/dev/release_notes/index.html
                  @@ -1,4 +1,4 @@
                  - Release notes - Django-Components      

                  Release notesΒ€

                  v0.115Β€

                  FixΒ€

                  • Fix integration with ManifestStaticFilesStorage on Windows by resolving component filepaths (like Component.template_name) to POSIX paths.

                  v0.114Β€

                  FixΒ€

                  • Prevent rendering Slot tags during fill discovery stage to fix a case when a component inside a slot fill tried to access provided data too early.

                  v0.113Β€

                  FixΒ€

                  • Ensure consistent order of scripts in Component.Media.js

                  v0.112Β€

                  FixΒ€

                  • Allow components to accept default fill even if no default slot was encountered during rendering

                  v0.111Β€

                  FixΒ€

                  • Prevent rendering Component tags during fill discovery stage to fix a case when a component inside the default slot tried to access provided data too early.

                  πŸš¨πŸ“’ v0.110Β€

                  GeneralΒ€

                  πŸš¨πŸ“’ BREAKING CHANGESΒ€

                  • Installation changes:

                    • If your components include JS or CSS, you now must use the middleware and add django-components' URLs to your urlpatterns (See "Adding support for JS and CSS")
                  • Component typing signature changed from

                    Component[Args, Kwargs, Data, Slots]
                    + Release notes - Django-Components      

                    Release notesΒ€

                    v0.115Β€

                    FixΒ€

                    • Fix integration with ManifestStaticFilesStorage on Windows by resolving component filepaths (like Component.template_name) to POSIX paths.

                    v0.114Β€

                    FixΒ€

                    • Prevent rendering Slot tags during fill discovery stage to fix a case when a component inside a slot fill tried to access provided data too early.

                    v0.113Β€

                    FixΒ€

                    • Ensure consistent order of scripts in Component.Media.js

                    v0.112Β€

                    FixΒ€

                    • Allow components to accept default fill even if no default slot was encountered during rendering

                    v0.111Β€

                    FixΒ€

                    • Prevent rendering Component tags during fill discovery stage to fix a case when a component inside the default slot tried to access provided data too early.

                    πŸš¨πŸ“’ v0.110Β€

                    GeneralΒ€

                    πŸš¨πŸ“’ BREAKING CHANGESΒ€

                    • Installation changes:

                      • If your components include JS or CSS, you now must use the middleware and add django-components' URLs to your urlpatterns (See "Adding support for JS and CSS")
                    • Component typing signature changed from

                      Component[Args, Kwargs, Data, Slots]
                       

                      to

                      Component[Args, Kwargs, Slots, Data, JsData, CssData]
                       
                    • If you rendered a component A with Component.render() and then inserted that into another component B, now you must pass render_dependencies=False to component A:

                      prerendered_a = CompA.render(
                           args=[...],
                      diff --git a/dev/scripts/extensions.py b/dev/scripts/extensions.py
                      index b7fbf26c..7197d85b 100644
                      --- a/dev/scripts/extensions.py
                      +++ b/dev/scripts/extensions.py
                      @@ -2,9 +2,9 @@ from pathlib import Path
                       from typing import List, Optional, Type
                       
                       import griffe
                      +from mkdocs_util import get_mkdocstrings_plugin_handler_options, import_object, load_config
                       
                       from django_components.util.misc import get_import_path
                      -from docs.scripts.mkdocs import get_mkdocstrings_plugin_handler_options, import_object, load_config
                       
                       SOURCE_CODE_GIT_BRANCH = "master"
                       
                      diff --git a/dev/scripts/mkdocs.py b/dev/scripts/mkdocs_util.py
                      similarity index 100%
                      rename from dev/scripts/mkdocs.py
                      rename to dev/scripts/mkdocs_util.py
                      diff --git a/dev/scripts/reference.py b/dev/scripts/reference.py
                      index bd85145c..57461fab 100644
                      --- a/dev/scripts/reference.py
                      +++ b/dev/scripts/reference.py
                      @@ -36,7 +36,6 @@ we don't have to run it manually. It will be run each time mkdocs is built.
                       """
                       
                       import inspect
                      -import os
                       import re
                       import sys
                       from argparse import ArgumentParser
                      @@ -59,16 +58,14 @@ from django_components.util.misc import get_import_path
                       #         - By default we can't do relative imports (e.g. `.extensions`)
                       #         - We can't import from packages found in the `src` directory (e.g. `docs.scripts.extensions`)
                       #
                      -#       But we need to import from another module.
                      -#       Hence we add the `src` directory to `sys.path` ourselves, so we can import from the
                      -#       `docs.scripts.extensions` module.
                      -current_dir = os.path.dirname(os.path.abspath(__file__))
                      -src_dir = os.path.abspath(os.path.join(current_dir, "..", ".."))
                      -sys.path.insert(0, src_dir)
                      +#       But we need to import from another module in ./docs/scripts.
                      +#       Hence we add the directory of this file to `sys.path` ourselves.
                       
                      -from docs.scripts.extensions import _format_source_code_html  # noqa: E402
                      +current_dir = str(Path(__file__).parent)
                      +sys.path.append(current_dir)
                      +from extensions import _format_source_code_html  # noqa: E402
                       
                      -root = Path(__file__).parent.parent.parent.parent
                      +root = Path(__file__).parent.parent.parent
                       
                       
                       def gen_reference_api():
                      @@ -81,11 +78,11 @@ def gen_reference_api():
                           module = import_module("django_components")
                       
                           preface = "\n\n"
                      -    preface += (root / "src/docs/templates/reference_api.md").read_text()
                      -    out_file = root / "src/docs/reference/api.md"
                      +    preface += (root / "docs/templates/reference_api.md").read_text()
                      +    out_file = root / "docs/reference/api.md"
                       
                           out_file.parent.mkdir(parents=True, exist_ok=True)
                      -    with out_file.open("w") as f:
                      +    with out_file.open("w", encoding="utf-8") as f:
                               f.write(preface + "\n\n")
                       
                               for name, obj in inspect.getmembers(module):
                      @@ -118,11 +115,11 @@ def gen_reference_exceptions():
                           module = import_module("django_components")
                       
                           preface = "\n\n"
                      -    preface += (root / "src/docs/templates/reference_exceptions.md").read_text()
                      -    out_file = root / "src/docs/reference/exceptions.md"
                      +    preface += (root / "docs/templates/reference_exceptions.md").read_text()
                      +    out_file = root / "docs/reference/exceptions.md"
                       
                           out_file.parent.mkdir(parents=True, exist_ok=True)
                      -    with out_file.open("w") as f:
                      +    with out_file.open("w", encoding="utf-8") as f:
                               f.write(preface + "\n\n")
                       
                               for name, obj in inspect.getmembers(module):
                      @@ -153,11 +150,11 @@ def gen_reference_components():
                           module = import_module("django_components.components")
                       
                           preface = "\n\n"
                      -    preface += (root / "src/docs/templates/reference_components.md").read_text()
                      -    out_file = root / "src/docs/reference/components.md"
                      +    preface += (root / "docs/templates/reference_components.md").read_text()
                      +    out_file = root / "docs/reference/components.md"
                       
                           out_file.parent.mkdir(parents=True, exist_ok=True)
                      -    with out_file.open("w") as f:
                      +    with out_file.open("w", encoding="utf-8") as f:
                               f.write(preface + "\n\n")
                       
                               for name, obj in inspect.getmembers(module):
                      @@ -203,11 +200,11 @@ def gen_reference_settings():
                           module = import_module("django_components.app_settings")
                       
                           preface = "\n\n"
                      -    preface += (root / "src/docs/templates/reference_settings.md").read_text()
                      -    out_file = root / "src/docs/reference/settings.md"
                      +    preface += (root / "docs/templates/reference_settings.md").read_text()
                      +    out_file = root / "docs/reference/settings.md"
                       
                           out_file.parent.mkdir(parents=True, exist_ok=True)
                      -    with out_file.open("w") as f:
                      +    with out_file.open("w", encoding="utf-8") as f:
                               # 1. Insert section from `reference_settings.md`
                               f.write(preface + "\n\n")
                       
                      @@ -260,7 +257,7 @@ def _get_unique_methods(base_class: Type, sub_class: Type):
                       
                       
                       def _gen_default_settings_section(app_settings_filepath: str) -> str:
                      -    # In the soure code (`app_settings.py`), we've inserted following strings
                      +    # In the source code (`app_settings.py`), we've inserted following strings
                           # to mark the start and end of the where we define the default settings.
                           # We copy this as a plain string, so that the comments are preserved.
                           settings_sourcecode = Path(app_settings_filepath).read_text()
                      @@ -308,11 +305,11 @@ def gen_reference_middlewares():
                           module = import_module("django_components.middleware")
                       
                           preface = "\n\n"
                      -    preface += (root / "src/docs/templates/reference_middlewares.md").read_text()
                      -    out_file = root / "src/docs/reference/middlewares.md"
                      +    preface += (root / "docs/templates/reference_middlewares.md").read_text()
                      +    out_file = root / "docs/reference/middlewares.md"
                       
                           out_file.parent.mkdir(parents=True, exist_ok=True)
                      -    with out_file.open("w") as f:
                      +    with out_file.open("w", encoding="utf-8") as f:
                               f.write(preface + "\n\n")
                       
                               for name, obj in inspect.getmembers(module):
                      @@ -351,8 +348,8 @@ def gen_reference_tagformatters():
                           module = import_module("django_components")
                       
                           preface = "\n\n"
                      -    preface += (root / "src/docs/templates/reference_tagformatters.md").read_text()
                      -    out_file = root / "src/docs/reference/tag_formatters.md"
                      +    preface += (root / "docs/templates/reference_tagformatters.md").read_text()
                      +    out_file = root / "docs/reference/tag_formatters.md"
                       
                           tag_formatter_classes: Dict[str, Type[TagFormatterABC]] = {}
                           tag_formatter_instances: Dict[str, TagFormatterABC] = {}
                      @@ -363,10 +360,10 @@ def gen_reference_tagformatters():
                                   tag_formatter_classes[name] = obj
                       
                           out_file.parent.mkdir(parents=True, exist_ok=True)
                      -    with out_file.open("w") as f:
                      +    with out_file.open("w", encoding="utf-8") as f:
                               f.write(preface + "\n\n")
                       
                      -        # Generate a summary of avilable tag formatters.
                      +        # Generate a summary of available tag formatters.
                               # For each pre-defined TagFormatter entry, generate e.g.
                               # ```markdown
                               # - `django_components.component_formatter` for [ComponentFormatter](#django_components.ComponentFormatter)
                      @@ -414,13 +411,13 @@ def gen_reference_urls():
                           module = import_module("django_components.urls")
                       
                           preface = "\n\n"
                      -    preface += (root / "src/docs/templates/reference_urls.md").read_text()
                      -    out_file = root / "src/docs/reference/urls.md"
                      +    preface += (root / "docs/templates/reference_urls.md").read_text()
                      +    out_file = root / "docs/reference/urls.md"
                       
                           all_urls = _list_urls(module.urlpatterns)
                       
                           out_file.parent.mkdir(parents=True, exist_ok=True)
                      -    with out_file.open("w") as f:
                      +    with out_file.open("w", encoding="utf-8") as f:
                               f.write(preface + "\n\n")
                       
                               # Simply list all URLs, e.g.
                      @@ -442,11 +439,11 @@ def gen_reference_commands():
                           ]
                       
                           preface = "\n\n"
                      -    preface += (root / "src/docs/templates/reference_commands.md").read_text()
                      -    out_file = root / "src/docs/reference/commands.md"
                      +    preface += (root / "docs/templates/reference_commands.md").read_text()
                      +    out_file = root / "docs/reference/commands.md"
                       
                           out_file.parent.mkdir(parents=True, exist_ok=True)
                      -    with out_file.open("w") as f:
                      +    with out_file.open("w", encoding="utf-8") as f:
                               f.write(preface + "\n\n")
                       
                               for cmd_name, cmd_path in command_modules:
                      @@ -459,7 +456,7 @@ def gen_reference_commands():
                                   formatted_args = _format_command_args(cmd_parser)
                       
                                   # Add link to source code
                      -            module_rel_path = Path(cmd_module.__file__).relative_to(Path.cwd())  # type: ignore[arg-type]
                      +            module_rel_path = Path(cmd_module.__file__).relative_to(Path.cwd()).as_posix()  # type: ignore[arg-type]
                                   obj_lineno = inspect.findsource(cmd_cls)[1]
                                   source_code_link = _format_source_code_html(module_rel_path, obj_lineno)
                       
                      @@ -490,16 +487,16 @@ def gen_reference_templatetags():
                           ]
                       
                           preface = "\n\n"
                      -    preface += (root / "src/docs/templates/reference_templatetags.md").read_text()
                      -    out_file = root / "src/docs/reference/template_tags.md"
                      +    preface += (root / "docs/templates/reference_templatetags.md").read_text()
                      +    out_file = root / "docs/reference/template_tags.md"
                       
                           out_file.parent.mkdir(parents=True, exist_ok=True)
                      -    with out_file.open("w") as f:
                      +    with out_file.open("w", encoding="utf-8") as f:
                               f.write(preface + "\n\n")
                       
                               for mod_name, mod_path in tags_modules:
                                   tags_module = import_module(mod_path)
                      -            module_rel_path = Path(tags_module.__file__).relative_to(Path.cwd())  # type: ignore[arg-type]
                      +            module_rel_path = Path(tags_module.__file__).relative_to(Path.cwd()).as_posix()  # type: ignore[arg-type]
                       
                                   f.write(
                                       f"All following template tags are defined in\n\n"
                      @@ -543,11 +540,11 @@ def gen_reference_templatevars():
                           under the `{{ component_vars }}` variable, as defined by `ComponentVars`.
                           """
                           preface = "\n\n"
                      -    preface += (root / "src/docs/templates/reference_templatevars.md").read_text()
                      -    out_file = root / "src/docs/reference/template_vars.md"
                      +    preface += (root / "docs/templates/reference_templatevars.md").read_text()
                      +    out_file = root / "docs/reference/template_vars.md"
                       
                           out_file.parent.mkdir(parents=True, exist_ok=True)
                      -    with out_file.open("w") as f:
                      +    with out_file.open("w", encoding="utf-8") as f:
                               f.write(preface + "\n\n")
                       
                               for field in ComponentVars._fields:
                      diff --git a/dev/sitemap.xml b/dev/sitemap.xml
                      index a68f15d1..3ae35ab1 100644
                      --- a/dev/sitemap.xml
                      +++ b/dev/sitemap.xml
                      @@ -2,194 +2,194 @@
                       
                           
                                https://emilstenstrom.github.io/django-components/latest/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/SUMMARY/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/migrating_from_safer_staticfiles/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/release_notes/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/advanced/authoring_component_libraries/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/advanced/component_registry/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/advanced/hooks/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/advanced/provide_inject/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/advanced/rendering_js_css/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/advanced/tag_formatter/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/advanced/typing_and_validation/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/access_component_input/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/autodiscovery/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/component_context_scope/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/components_as_views/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/components_in_python/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/components_in_templates/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/defining_js_css_html_files/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/html_attributes/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/single_file_components/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/slots/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/template_tag_syntax/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/concepts/fundamentals/your_first_component/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/devguides/dependency_mgmt/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/devguides/slot_rendering/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/devguides/slots_and_blocks/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/guides/setup/dev_server_setup/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/guides/setup/logging_and_debugging/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/guides/setup/syntax_highlight/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/overview/code_of_conduct/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/overview/community/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/overview/compatibility/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/overview/contributing/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/overview/development/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/overview/installation/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/overview/license/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/overview/security_notes/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/overview/welcome/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/reference/api/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/reference/commands/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/reference/components/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/reference/exceptions/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/reference/middlewares/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/reference/settings/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/reference/tag_formatters/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/reference/template_tags/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/reference/template_vars/
                      -         2024-12-02
                      +         2024-12-03
                           
                           
                                https://emilstenstrom.github.io/django-components/latest/reference/urls/
                      -         2024-12-02
                      +         2024-12-03
                           
                       
                      \ No newline at end of file
                      diff --git a/dev/sitemap.xml.gz b/dev/sitemap.xml.gz
                      index 4cd80401..4cfbe279 100644
                      Binary files a/dev/sitemap.xml.gz and b/dev/sitemap.xml.gz differ
                      diff --git a/versions.json b/versions.json
                      index 152714c3..3a88e34e 100644
                      --- a/versions.json
                      +++ b/versions.json
                      @@ -1,7 +1,7 @@
                       [
                         {
                           "version": "dev",
                      -    "title": "dev (cdc830f)",
                      +    "title": "dev (594c068)",
                           "aliases": []
                         },
                         {