mirror of
https://github.com/django-components/django-components.git
synced 2025-07-07 17:34:59 +00:00
docs: Syntax highlighting for mkdocs (#984)
* feat:forward context processors variables in context in ISOLATED mode provide context_processors_data property to Component to access those variables in Component * refactor: internalize RequestContext and pass HttpRequest internally * docs: document HttpRequest and context processors * docs: use djc_py code blocks for component definitions --------- Co-authored-by: Lilian Durey <dureylilian@gmail.com>
This commit is contained in:
parent
1f7e28db22
commit
314ec77d3d
26 changed files with 142 additions and 76 deletions
|
@ -105,7 +105,7 @@ For live examples, see the [Community examples](../../overview/community.md#comm
|
|||
|
||||
It's also a good idea to have a common prefix for your components, so they can be easily distinguished from users' components. In the example below, we use the prefix `my_` / `My`.
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
from typing import Dict, NotRequired, Optional, Tuple, TypedDict
|
||||
|
||||
from django_components import Component, SlotFunc, register, types
|
||||
|
|
|
@ -106,7 +106,7 @@ Then navigate to these URLs:
|
|||
|
||||
### 1. Define document HTML
|
||||
|
||||
```py title="[root]/components/demo.py"
|
||||
```djc_py title="[root]/components/demo.py"
|
||||
from django_components import Component, types
|
||||
|
||||
# HTML into which a fragment will be loaded using HTMX
|
||||
|
@ -141,7 +141,7 @@ class MyPage(Component):
|
|||
|
||||
### 2. Define fragment HTML
|
||||
|
||||
```py title="[root]/components/demo.py"
|
||||
```djc_py title="[root]/components/demo.py"
|
||||
class Frag(Component):
|
||||
def get(self, request):
|
||||
return self.render_to_response(
|
||||
|
@ -184,7 +184,7 @@ urlpatterns = [
|
|||
|
||||
### 1. Define document HTML
|
||||
|
||||
```py title="[root]/components/demo.py"
|
||||
```djc_py title="[root]/components/demo.py"
|
||||
from django_components import Component, types
|
||||
|
||||
# HTML into which a fragment will be loaded using AlpineJS
|
||||
|
@ -225,7 +225,7 @@ class MyPage(Component):
|
|||
|
||||
### 2. Define fragment HTML
|
||||
|
||||
```py title="[root]/components/demo.py"
|
||||
```djc_py title="[root]/components/demo.py"
|
||||
class Frag(Component):
|
||||
def get(self, request):
|
||||
# IMPORTANT: Don't forget `type="fragment"`
|
||||
|
@ -281,7 +281,7 @@ urlpatterns = [
|
|||
|
||||
### 1. Define document HTML
|
||||
|
||||
```py title="[root]/components/demo.py"
|
||||
```djc_py title="[root]/components/demo.py"
|
||||
from django_components import Component, types
|
||||
|
||||
# HTML into which a fragment will be loaded using JS
|
||||
|
@ -321,7 +321,7 @@ class MyPage(Component):
|
|||
|
||||
### 2. Define fragment HTML
|
||||
|
||||
```py title="[root]/components/demo.py"
|
||||
```djc_py title="[root]/components/demo.py"
|
||||
class Frag(Component):
|
||||
def get(self, request):
|
||||
return self.render_to_response(
|
||||
|
|
|
@ -107,7 +107,7 @@ have all the keys that were passed to the `provide` tag.
|
|||
|
||||
## Full example
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
@register("child")
|
||||
class ChildComponent(Component):
|
||||
template = """
|
||||
|
|
|
@ -27,7 +27,7 @@ the locations by inserting following Django template tags:
|
|||
|
||||
So if you have a component with JS and CSS:
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
from django_components import Component, types
|
||||
|
||||
class MyButton(Component):
|
||||
|
|
|
@ -85,9 +85,9 @@ This has two modes:
|
|||
|
||||
Consider this example:
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
class Outer(Component):
|
||||
template = \"\"\"
|
||||
template = """
|
||||
<div>
|
||||
{% component "inner" %}
|
||||
{% fill "content" %}
|
||||
|
@ -95,7 +95,7 @@ This has two modes:
|
|||
{% endfill %}
|
||||
{% endcomponent %}
|
||||
</div>
|
||||
\"\"\"
|
||||
"""
|
||||
```
|
||||
|
||||
- `"django"` - `my_var` has access to data from `get_context_data()` of both `Inner` and `Outer`.
|
||||
|
@ -108,7 +108,7 @@ This has two modes:
|
|||
|
||||
Given this template:
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
@register("root_comp")
|
||||
class RootComp(Component):
|
||||
template = """
|
||||
|
@ -148,7 +148,7 @@ all the data defined in the outer layers, like the `{% with %}` tag.
|
|||
|
||||
Given this template:
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
class RootComp(Component):
|
||||
template = """
|
||||
{% with cheese="feta" %}
|
||||
|
|
|
@ -19,7 +19,7 @@ Components can now be used as views:
|
|||
|
||||
Here's an example of a calendar component defined as a view:
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
# In a file called [project root]/components/calendar.py
|
||||
from django_components import Component, ComponentView, register
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ Components can be rendered outside of Django templates, calling them as regular
|
|||
|
||||
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:
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
class SimpleComponent(Component):
|
||||
template = """
|
||||
{% load component_tags %}
|
||||
|
|
|
@ -28,7 +28,7 @@ HTML / JS / CSS with a component:
|
|||
|
||||
However, you can freely mix these for different languages:
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
class MyTable(Component):
|
||||
template: types.django_html = """
|
||||
<div class="welcome">
|
||||
|
|
|
@ -256,7 +256,7 @@ Then:
|
|||
|
||||
## Full example for `html_attrs`
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
@register("my_comp")
|
||||
class MyComp(Component):
|
||||
template: t.django_html = """
|
||||
|
|
|
@ -78,7 +78,7 @@ rendered = template.render(RequestContext(request, {}))
|
|||
|
||||
The data from context processors is automatically available within the component's template.
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
class MyComponent(Component):
|
||||
template = """
|
||||
<div>
|
||||
|
|
|
@ -9,7 +9,7 @@ For example, here's the calendar component from
|
|||
the [Getting started](../../getting_started/your_first_component.md) tutorial,
|
||||
defined in a single file:
|
||||
|
||||
```python title="[project root]/components/calendar.py"
|
||||
```djc_py title="[project root]/components/calendar.py"
|
||||
from django_components import Component, register, types
|
||||
|
||||
@register("calendar")
|
||||
|
|
|
@ -469,7 +469,7 @@ _Added in version 0.76_:
|
|||
|
||||
Consider a component with slot(s). This component may do some processing on the inputs, and then use the processed variable in the slot's default template:
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
@register("my_comp")
|
||||
class MyComp(Component):
|
||||
template = """
|
||||
|
@ -498,7 +498,7 @@ Using scoped slots consists of two steps:
|
|||
|
||||
To pass the data to the `slot` tag, simply pass them as keyword attributes (`key=value`):
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
@register("my_comp")
|
||||
class MyComp(Component):
|
||||
template = """
|
||||
|
@ -649,14 +649,14 @@ So it's possible to define a `name` key on a dictionary, and then spread that on
|
|||
You can dynamically pass all slots to a child component. This is similar to
|
||||
[passing all slots in Vue](https://vue-land.github.io/faq/forwarding-slots#passing-all-slots):
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
class MyTable(Component):
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
return {
|
||||
"slots": self.input.slots,
|
||||
}
|
||||
|
||||
template: """
|
||||
template = """
|
||||
<div>
|
||||
{% component "child" %}
|
||||
{% for slot_name in slots %}
|
||||
|
|
|
@ -25,7 +25,7 @@ inheritance follows these rules:
|
|||
|
||||
For example:
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
class BaseCard(Component):
|
||||
template = """
|
||||
<div class="card">
|
||||
|
@ -37,7 +37,7 @@ class BaseCard(Component):
|
|||
border: 1px solid gray;
|
||||
}
|
||||
"""
|
||||
js = "console.log('Base card loaded');"
|
||||
js = """console.log('Base card loaded');"""
|
||||
|
||||
# This class overrides parent's template, but inherits CSS and JS
|
||||
class SpecialCard(BaseCard):
|
||||
|
@ -94,7 +94,7 @@ All other attributes and methods (including the [`Component.View`](../../referen
|
|||
|
||||
For example:
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
class BaseForm(Component):
|
||||
template = """
|
||||
<form>
|
||||
|
|
|
@ -202,7 +202,7 @@ of HTML attributes (usually called `attrs`) to pass to the underlying template.
|
|||
In such cases, we may want to define some HTML attributes statically, and other dynamically.
|
||||
But for that, we need to define this dictionary on Python side:
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
@register("my_comp")
|
||||
class MyComp(Component):
|
||||
template = """
|
||||
|
@ -229,7 +229,7 @@ as component kwargs, so we can keep all the relevant information in the template
|
|||
we prefix the key with the name of the dict and `:`. So key `class` of input `attrs` becomes
|
||||
`attrs:class`. And our example becomes:
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
@register("my_comp")
|
||||
class MyComp(Component):
|
||||
template = """
|
||||
|
|
|
@ -50,7 +50,7 @@ class Calendar(Component):
|
|||
|
||||
Alternatively, you can "inline" HTML, JS, and CSS right into the component class:
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
from django_components import Component
|
||||
|
||||
class Calendar(Component):
|
||||
|
|
|
@ -7,7 +7,7 @@ associated with components, and how we render them.
|
|||
|
||||
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`:
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
from django_components import Component, types
|
||||
|
||||
class MyTable(Component):
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
```
|
||||
|
||||
And components that make use of `abc.html` via `include` or `extends`:
|
||||
```py
|
||||
```djc_py
|
||||
from django_components import Component, register
|
||||
|
||||
@register("my_comp_extends")
|
||||
|
@ -66,7 +66,7 @@
|
|||
```py
|
||||
@register("my_comp")
|
||||
class MyComp(Component):
|
||||
template_file = "abc.html"
|
||||
template_file = "abc.html"
|
||||
```
|
||||
|
||||
Then:
|
||||
|
@ -110,37 +110,34 @@
|
|||
uses `extends`. In that case, just as you would expect, the `block inner` inside
|
||||
`abc.html` will render `OVERRIDEN`:
|
||||
|
||||
````py
|
||||
```djc_py
|
||||
@register("my_comp")
|
||||
class MyComp(Component):
|
||||
template_file = """
|
||||
{% extends "abc.html" %}
|
||||
|
||||
{% block inner %}
|
||||
OVERRIDEN
|
||||
{% endblock %}
|
||||
"""
|
||||
```
|
||||
|
||||
````
|
||||
template = """
|
||||
{% extends "abc.html" %}
|
||||
{% block inner %}
|
||||
OVERRIDEN
|
||||
{% endblock %}
|
||||
"""
|
||||
```
|
||||
|
||||
4. This is where it gets interesting (but still intuitive). You can insert even
|
||||
new `slots` inside these "overriding" blocks:
|
||||
|
||||
```py
|
||||
```djc_py
|
||||
@register("my_comp")
|
||||
class MyComp(Component):
|
||||
template_file = """
|
||||
{% extends "abc.html" %}
|
||||
template = """
|
||||
{% extends "abc.html" %}
|
||||
|
||||
{% load component_tags %}
|
||||
{% block "inner" %}
|
||||
OVERRIDEN
|
||||
{% slot "new_slot" %}
|
||||
hello
|
||||
{% endslot %}
|
||||
{% endblock %}
|
||||
"""
|
||||
{% load component_tags %}
|
||||
{% block "inner" %}
|
||||
OVERRIDEN
|
||||
{% slot "new_slot" %}
|
||||
hello
|
||||
{% endslot %}
|
||||
{% endblock %}
|
||||
"""
|
||||
```
|
||||
|
||||
And you can then pass fill for this `new_slot` when rendering the component:
|
||||
|
|
|
@ -9,7 +9,7 @@ weight: 1
|
|||
|
||||
2. Next, in your component, set typings of `Component.template/css/js` to `types.django_html`, `types.css`, and `types.js` respectively. The extension will recognize these and will activate syntax highlighting.
|
||||
|
||||
```python title="[project root]/components/calendar.py"
|
||||
```djc_py title="[project root]/components/calendar.py"
|
||||
# In a file called [project root]/components/calendar.py
|
||||
from django_components import Component, register, types
|
||||
|
||||
|
@ -21,12 +21,19 @@ class Calendar(Component):
|
|||
}
|
||||
|
||||
template: types.django_html = """
|
||||
<div class="calendar-component">Today's date is <span>{{ date }}</span></div>
|
||||
<div class="calendar-component">
|
||||
Today's date is <span>{{ date }}</span>
|
||||
</div>
|
||||
"""
|
||||
|
||||
css: types.css = """
|
||||
.calendar-component { width: 200px; background: pink; }
|
||||
.calendar-component span { font-weight: bold; }
|
||||
.calendar-component {
|
||||
width: 200px;
|
||||
background: pink;
|
||||
}
|
||||
.calendar-component span {
|
||||
font-weight: bold;
|
||||
}
|
||||
"""
|
||||
|
||||
js: types.js = """
|
||||
|
@ -43,7 +50,7 @@ class Calendar(Component):
|
|||
With PyCharm (or any other editor from Jetbrains), you don't need to use `types.django_html`, `types.css`, `types.js` since Pycharm uses [language injections](https://www.jetbrains.com/help/pycharm/using-language-injections.html).
|
||||
You only need to write the comments `# language=<lang>` above the variables.
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
from django_components import Component, register
|
||||
|
||||
@register("calendar")
|
||||
|
@ -55,13 +62,20 @@ class Calendar(Component):
|
|||
|
||||
# language=HTML
|
||||
template= """
|
||||
<div class="calendar-component">Today's date is <span>{{ date }}</span></div>
|
||||
<div class="calendar-component">
|
||||
Today's date is <span>{{ date }}</span>
|
||||
</div>
|
||||
"""
|
||||
|
||||
# language=CSS
|
||||
css = """
|
||||
.calendar-component { width: 200px; background: pink; }
|
||||
.calendar-component span { font-weight: bold; }
|
||||
.calendar-component {
|
||||
width: 200px;
|
||||
background: pink;
|
||||
}
|
||||
.calendar-component span {
|
||||
font-weight: bold;
|
||||
}
|
||||
"""
|
||||
|
||||
# language=JS
|
||||
|
@ -73,3 +87,45 @@ class Calendar(Component):
|
|||
})()
|
||||
"""
|
||||
```
|
||||
|
||||
## Pygments
|
||||
|
||||
[Pygments](https://pygments.org/) is a syntax highlighting library written in Python. It's also what's used by this documentation site ([mkdocs-material](https://squidfunk.github.io/mkdocs-material/)) to highlight code blocks.
|
||||
|
||||
To write code blocks with syntax highlighting, you need to install the [`pygments-djc`](https://pypi.org/project/pygments-djc/) package.
|
||||
|
||||
```bash
|
||||
pip install pygments-djc
|
||||
```
|
||||
|
||||
And then initialize it by importing `pygments_djc`:
|
||||
|
||||
```python
|
||||
import pygments_djc
|
||||
```
|
||||
|
||||
Now you can write code blocks with syntax highlighting.
|
||||
|
||||
```txt
|
||||
\```djc_py
|
||||
from django_components import Component, register
|
||||
|
||||
@register("calendar")
|
||||
class Calendar(Component):
|
||||
template= """
|
||||
<div class="calendar-component">
|
||||
Today's date is <span>{{ date }}</span>
|
||||
</div>
|
||||
"""
|
||||
|
||||
css = """
|
||||
.calendar-component {
|
||||
width: 200px;
|
||||
background: pink;
|
||||
}
|
||||
.calendar-component span {
|
||||
font-weight: bold;
|
||||
}
|
||||
"""
|
||||
\```
|
||||
```
|
||||
|
|
|
@ -88,7 +88,7 @@ Read on to learn about all the exciting details and configuration possibilities!
|
|||
- Each component can include its own HTML, CSS, and JS, or additional third-party JS and CSS.
|
||||
- HTML, CSS, and JS can be defined on the component class, or loaded from files.
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
from django_components import Component
|
||||
|
||||
@register("calendar")
|
||||
|
|
|
@ -14,7 +14,7 @@ the signal is triggered for each component.
|
|||
|
||||
Import from django as `django.test.signals.template_rendered`.
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
from django.test.signals import template_rendered
|
||||
|
||||
# Setup a callback function
|
||||
|
|
3
docs/scripts/setup.py
Normal file
3
docs/scripts/setup.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Allow us to use `djc_py` / `djc_python` code blocks.
|
||||
# Importing this package automatically registers the `djc_py` lexer onto Pygments.
|
||||
import pygments_djc # noqa: F401
|
2
docs/templates/reference_signals.md
vendored
2
docs/templates/reference_signals.md
vendored
|
@ -12,7 +12,7 @@ the signal is triggered for each component.
|
|||
|
||||
Import from django as `django.test.signals.template_rendered`.
|
||||
|
||||
```python
|
||||
```djc_py
|
||||
from django.test.signals import template_rendered
|
||||
|
||||
# Setup a callback function
|
||||
|
|
|
@ -123,6 +123,7 @@ plugins:
|
|||
closing_tag: "!}"
|
||||
- gen-files:
|
||||
scripts:
|
||||
- docs/scripts/setup.py
|
||||
- docs/scripts/reference.py
|
||||
- literate-nav:
|
||||
nav_file: SUMMARY.md
|
||||
|
|
|
@ -11,4 +11,5 @@ mypy
|
|||
playwright
|
||||
requests
|
||||
types-requests
|
||||
whitenoise
|
||||
whitenoise
|
||||
pygments-djc
|
|
@ -8,7 +8,7 @@ asgiref==3.8.1
|
|||
# via django
|
||||
black==24.10.0
|
||||
# via -r requirements-dev.in
|
||||
cachetools==5.5.0
|
||||
cachetools==5.5.1
|
||||
# via tox
|
||||
certifi==2024.8.30
|
||||
# via requests
|
||||
|
@ -16,15 +16,15 @@ cfgv==3.4.0
|
|||
# via pre-commit
|
||||
chardet==5.2.0
|
||||
# via tox
|
||||
charset-normalizer==3.4.0
|
||||
charset-normalizer==3.4.1
|
||||
# via requests
|
||||
click==8.1.7
|
||||
click==8.1.8
|
||||
# via black
|
||||
colorama==0.4.6
|
||||
# via tox
|
||||
distlib==0.3.9
|
||||
# via virtualenv
|
||||
django==5.1.5
|
||||
django==5.1.6
|
||||
# via -r requirements-dev.in
|
||||
djc-core-html-parser==1.0.1
|
||||
# via -r requirements-dev.in
|
||||
|
@ -32,7 +32,7 @@ filelock==3.16.1
|
|||
# via
|
||||
# tox
|
||||
# virtualenv
|
||||
flake8==7.1.1
|
||||
flake8==7.1.2
|
||||
# via
|
||||
# -r requirements-dev.in
|
||||
# flake8-pyproject
|
||||
|
@ -40,7 +40,7 @@ flake8-pyproject==1.2.3
|
|||
# via -r requirements-dev.in
|
||||
greenlet==3.1.1
|
||||
# via playwright
|
||||
identify==2.6.3
|
||||
identify==2.6.7
|
||||
# via pre-commit
|
||||
idna==3.10
|
||||
# via requests
|
||||
|
@ -85,6 +85,10 @@ pyee==12.0.0
|
|||
# via playwright
|
||||
pyflakes==3.2.0
|
||||
# via flake8
|
||||
pygments==2.19.1
|
||||
# via pygments-djc
|
||||
pygments-djc==1.0.1
|
||||
# via -r requirements-dev.in
|
||||
pyproject-api==1.8.0
|
||||
# via tox
|
||||
pytest==8.3.4
|
||||
|
@ -93,7 +97,7 @@ pyyaml==6.0.2
|
|||
# via pre-commit
|
||||
requests==2.32.3
|
||||
# via -r requirements-dev.in
|
||||
sqlparse==0.5.2
|
||||
sqlparse==0.5.3
|
||||
# via django
|
||||
tox==4.24.1
|
||||
# via -r requirements-dev.in
|
||||
|
|
|
@ -59,7 +59,7 @@ cssselect2==0.7.0
|
|||
# via cairosvg
|
||||
defusedxml==0.7.1
|
||||
# via cairosvg
|
||||
django==5.1.5
|
||||
django==5.1.6
|
||||
# via hatch.envs.docs
|
||||
ghp-import==2.1.0
|
||||
# via mkdocs
|
||||
|
@ -178,7 +178,11 @@ platformdirs==4.3.6
|
|||
pycparser==2.22
|
||||
# via cffi
|
||||
pygments==2.19.1
|
||||
# via mkdocs-material
|
||||
# via
|
||||
# mkdocs-material
|
||||
# pygments-djc
|
||||
pygments-djc==1.0.1
|
||||
# via -r requirements-dev.in
|
||||
pymdown-extensions==10.14.3
|
||||
# via
|
||||
# hatch.envs.docs
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue