Merging upstream version 0.46.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
d5bf7afd18
commit
76fe8c2886
125 changed files with 8421 additions and 71 deletions
127
docs/theme/Autodoc.jinja
vendored
Normal file
127
docs/theme/Autodoc.jinja
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
{#def
|
||||
obj: dict | None = None,
|
||||
name: str = "",
|
||||
level: int = 2,
|
||||
members: bool = True,
|
||||
#}
|
||||
|
||||
{% set obj = obj or autodoc(name) %}
|
||||
|
||||
<h{{ level }}>
|
||||
<code class="doc-symbol doc-symbol-{{ obj.symbol }}">{{ obj.symbol }}</code>
|
||||
<span class="doc-oname doc-oname-{{ obj.symbol }}">{{ name or obj.name }}</span>
|
||||
{% if obj.label -%}
|
||||
<small class="doc-olabel doc-olabel-{{ obj.label }}">
|
||||
<code>{{ obj.label }}</code>
|
||||
</small>
|
||||
{%- endif %}
|
||||
</h{{ level }}>
|
||||
|
||||
{%- if obj.short_description -%}
|
||||
<div class="doc-short-description">
|
||||
{{ obj.short_description | markdown | utils.widont }}
|
||||
</div>
|
||||
{% endif -%}
|
||||
|
||||
{%- if obj.signature -%}
|
||||
<div class="doc-signature">
|
||||
{% filter markdown -%}
|
||||
```python
|
||||
{{ obj.signature }}
|
||||
```
|
||||
{%- endfilter %}
|
||||
</div>
|
||||
{%- endif %}
|
||||
|
||||
{% if obj.bases -%}
|
||||
<div class="doc-bases">
|
||||
<p>Bases:
|
||||
{%- for base in obj.bases %} <code>{{ base }}</code>{% if not loop.last %}, {% endif %}
|
||||
{%- endfor %}
|
||||
</p>
|
||||
</div>
|
||||
{%- endif %}
|
||||
|
||||
{% if obj.params -%}
|
||||
<table class="doc-arguments">
|
||||
<thead><tr><th>Argument</th><th>Description</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for param in obj.params %}
|
||||
<tr>
|
||||
<td><code>{{ param.name }}</code></td>
|
||||
<td>{{ param.description | markdown | utils.widont }}</td>
|
||||
</tr>
|
||||
{%- endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{%- endif %}
|
||||
|
||||
{%- if obj.description -%}
|
||||
<div class="doc-long-description">
|
||||
{{ obj.description | markdown | utils.widont }}
|
||||
</div>
|
||||
{% endif -%}
|
||||
|
||||
{% if obj.examples -%}
|
||||
<div class="doc-examples">
|
||||
<p><strong>Example:</strong></p>
|
||||
|
||||
{% for ex in obj.examples -%}
|
||||
<div>
|
||||
{% if ex.description %}{{ ex.description | markdown | utils.widont }}{% endif %}
|
||||
{% if ex.snippet %}{{ ex.snippet }}{% endif %}
|
||||
<div>
|
||||
{% endfor -%}
|
||||
</div>
|
||||
{%- endif %}
|
||||
|
||||
{% if obj.returns -%}
|
||||
<li class="doc-returns">
|
||||
<p><strong>Returns:</strong></p>
|
||||
|
||||
{% if ex.returns -%}
|
||||
<p>{{ obj.returns }}</p>
|
||||
{%- endif %}
|
||||
{% if ex.many_returns -%}
|
||||
<ul>
|
||||
{% for return in ex.many_returns %}
|
||||
<li>{{ return }}</li>
|
||||
{%- endfor %}
|
||||
</ul>
|
||||
{%- endif %}
|
||||
</div>
|
||||
{%- endif %}
|
||||
|
||||
{% if obj.raises -%}
|
||||
<div class="doc-raises"></div>
|
||||
<p><strong>Raises:</strong></p>
|
||||
|
||||
<ul>
|
||||
{% for raises in obj.raises -%}
|
||||
<li>{{ raises.description | markdown | utils.widont }}<ul>
|
||||
{% endfor -%}
|
||||
</ul>
|
||||
</li>
|
||||
{%- endif %}
|
||||
|
||||
{% if members -%}
|
||||
{% if obj.attrs or obj.properties-%}
|
||||
<div class="doc-attrs">
|
||||
{% for attr in obj.attrs -%}
|
||||
<Autodoc obj={{ attr }} level={{ level + 1 }} />
|
||||
{% endfor %}
|
||||
{% for attr in obj.properties %}
|
||||
<Autodoc obj={{ attr }} level={{ level + 1 }} />
|
||||
{%- endfor %}
|
||||
</div>
|
||||
{%- endif %}
|
||||
|
||||
{% if obj.methods -%}
|
||||
<div class="doc-methods">
|
||||
{% for method in obj.methods %}
|
||||
<Autodoc obj={{ method }} level={{ level + 1 }} />
|
||||
{%- endfor %}
|
||||
</div>
|
||||
{%- endif %}
|
||||
{%- endif %}
|
45
docs/theme/Callout.jinja
vendored
Normal file
45
docs/theme/Callout.jinja
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
{#def title="", type="info", icon="", open=True #}
|
||||
|
||||
{% set icons = {
|
||||
"note": "sticky_note",
|
||||
"info": "info",
|
||||
"tip": "check_circle",
|
||||
"alert": "release_alert",
|
||||
"warning": "warning",
|
||||
"danger": "release_alert",
|
||||
"error": "release_alert",
|
||||
"internal": "rocket_launch",
|
||||
"todo": "checklist",
|
||||
} %}
|
||||
|
||||
{% if icon != False %}
|
||||
{% set icon = icon or icons.get(type) %}
|
||||
{% endif %}
|
||||
|
||||
{% do attrs.set(class="type-" + type or "none") %}
|
||||
|
||||
{% if title -%}
|
||||
|
||||
<details {{ attrs.render(open=open, class="cd-callout", data_component="Callout") }}>
|
||||
<summary>
|
||||
{% if icon -%}
|
||||
<i class="icon">{{ icon }}</i>
|
||||
{% endif -%}
|
||||
{{ title }}
|
||||
<icon class="icon arrow">keyboard_arrow_down</icon>
|
||||
</summary>
|
||||
<div class="content">{{content}}</div>
|
||||
</details>
|
||||
|
||||
{%- else -%}
|
||||
|
||||
<aside {{ attrs.render(class="cd-callout", data_component="Callout") }}>
|
||||
{% if icon -%}
|
||||
<div class="icon-wrapper">
|
||||
<i class="icon">{{ icon }}</i>
|
||||
</div>
|
||||
{%- endif %}
|
||||
<div class="content">{{content}}</div>
|
||||
</aside>
|
||||
|
||||
{%- endif %}
|
27
docs/theme/ExampleTabs.jinja
vendored
Normal file
27
docs/theme/ExampleTabs.jinja
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
{#def prefix, panels={} #}
|
||||
|
||||
<div {{ attrs.render(
|
||||
class="cd-example-tabs not-prose",
|
||||
data_component="ExampleTabs",
|
||||
) }}>
|
||||
<TabGroup class="example-tabgroup">
|
||||
<TabList class="example-tablist" data-md-skip>
|
||||
{%- for text in panels.keys() %}
|
||||
<Tab
|
||||
class="example-tab"
|
||||
target={{ "ex-%s-%s" % (prefix, loop.index) }}
|
||||
selected={{ loop.index == 1 }}
|
||||
>{{ text }}</Tab>
|
||||
{%- endfor %}
|
||||
</TabList>
|
||||
{%- for name in panels.values() %}
|
||||
<TabPanel
|
||||
class="example-tabpanel"
|
||||
id={{ "ex-%s-%s" % (prefix, loop.index) }}
|
||||
hidden={{ loop.index != 1 }}
|
||||
>
|
||||
{{ catalog.irender(name) }}
|
||||
</TabPanel>
|
||||
{%- endfor %}
|
||||
</TabGroup>
|
||||
</div>
|
10
docs/theme/Footer.jinja
vendored
Normal file
10
docs/theme/Footer.jinja
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<footer {{ attrs.render(class="cd-footer", data_component="Footer") }}>
|
||||
<div class="wrapper">
|
||||
<Copyright />
|
||||
<div class="built-with">
|
||||
This site was
|
||||
<a title="Coming soon!">built using Claydocs</a>
|
||||
</div>
|
||||
<ThemeSwitch class="themeswitch" />
|
||||
</div>
|
||||
</footer>
|
17
docs/theme/Header.jinja
vendored
Normal file
17
docs/theme/Header.jinja
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
{#def title="", section="" #}
|
||||
|
||||
{% set section = section or page.section if section != false else None %}
|
||||
{% set title = title or page.title %}
|
||||
|
||||
<header {{ attrs.render(
|
||||
class="cd-header",
|
||||
data_component="Header",
|
||||
) }}>
|
||||
<div>
|
||||
{% if section -%}
|
||||
<div>{{ section }}</div>
|
||||
{%- endif %}
|
||||
<h1>{{ title | utils.widont }}</h1>
|
||||
</div>
|
||||
<p class="description">{{ content | utils.widont }}</p>
|
||||
</header>
|
25
docs/theme/Layout.jinja
vendored
Normal file
25
docs/theme/Layout.jinja
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
{#def title="", description="" #}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ page.lang }}" class="light">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<MetaTags page={{ page }} />
|
||||
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/static/img/apple-touch-icon.png">
|
||||
<link rel="stylesheet" href="/static/theme.css?v={{ utils.timestamp }}">
|
||||
<link rel="stylesheet" href="/static/prose.css?v={{ utils.timestamp }}">
|
||||
<link rel="stylesheet" href="/static/docs.css?v={{ utils.timestamp }}">
|
||||
{{ catalog.render_assets() }}
|
||||
{% if page.prev_page and page.prev_page.url -%}
|
||||
<link href="{{ page.prev_page.url }}" rel="prev">
|
||||
{% endif -%}
|
||||
{% if page.next_page and page.next_page.url -%}
|
||||
<link href="{{ page.next_page.url }}" rel="next">
|
||||
{% endif -%}
|
||||
<meta property="generator" content="claydocs" />
|
||||
</head>
|
||||
<body {{ attrs.render() }}>
|
||||
{{ content }}
|
||||
</body>
|
||||
</html>
|
22
docs/theme/MetaTags.jinja
vendored
Normal file
22
docs/theme/MetaTags.jinja
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
{#def page #}
|
||||
|
||||
{% set DEFAULT_TITLE = "JinjaX Documentation" %}
|
||||
{% set title = (page.title + " | " + DEFAULT_TITLE) if page.title else DEFAULT_TITLE %}
|
||||
{% set description = page.description %}
|
||||
|
||||
<title>{{ title }}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="{{ nav.domain }}{{ page.url }}">
|
||||
<meta property="og:title" content="{{ title }}">
|
||||
<meta property="twitter:title" content="{{ title }}">
|
||||
{% if description -%}
|
||||
<meta property="og:description" content="{{ description }}">
|
||||
<meta property="twitter:description" content="{{ description }}">
|
||||
{%- endif %}
|
||||
<meta property="og:image" content="{{ nav.domain }}{{ page.url }}/og-card.png">
|
||||
<meta property="og:image:type" content="image/png">
|
||||
<meta property="og:image:width" content="1200">
|
||||
<meta property="og:image:height" content="630">
|
||||
<meta property="twitter:card" content="summary_large_image">
|
||||
<meta property="twitter:image" content="{{ nav.domain }}{{ page.url }}/og-card.png">
|
3
docs/theme/NavBar.jinja
vendored
Normal file
3
docs/theme/NavBar.jinja
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
<nav {{ attrs.render(class="cd-navbar", data_component="NavBar") }}>
|
||||
{{ content }}
|
||||
</nav>
|
3
docs/theme/NavGlobal.jinja
vendored
Normal file
3
docs/theme/NavGlobal.jinja
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
<div {{ attrs.render(class="cd-nav-global scrollbar-thin", data_component="NavGlobal") }}>
|
||||
<Toc toc={{ nav.toc }} page={{ page}} />
|
||||
</div>
|
5
docs/theme/NavLocal.jinja
vendored
Normal file
5
docs/theme/NavLocal.jinja
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
<div {{ attrs.render(class="cd-nav-local", data_component="NavLocal") }}>
|
||||
<div class="wrapper scrollbar-thin">
|
||||
<TocPage :page_toc="page.toc" />
|
||||
</div>
|
||||
</div>
|
18
docs/theme/NavMobile.jinja
vendored
Normal file
18
docs/theme/NavMobile.jinja
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% do attrs.set(id="navMobile", class="cd-nav-mobile", data_component="NavMobile") %}
|
||||
|
||||
<Popover _attrs={{ attrs }}>
|
||||
<header>
|
||||
<Logo base_url={{ page.base_url }} class="logo" />
|
||||
<nav class="cd-navbar nav-links">
|
||||
<ThemeSwitch class="themeswitch" text={{ false }} />
|
||||
</nav>
|
||||
<PopButton
|
||||
target="navMobile"
|
||||
action="close"
|
||||
title="Close menu"
|
||||
class="cd-toggle-sidebar cd-text-button"
|
||||
>Close</PopButton>
|
||||
</header>
|
||||
|
||||
<Toc class="toc" toc={{ nav.toc }} page={{ page }} />
|
||||
</Popover>
|
17
docs/theme/NavTop.jinja
vendored
Normal file
17
docs/theme/NavTop.jinja
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
<section class="cd-nav-top", data_component="NavTop">
|
||||
<div class="wrapper">
|
||||
<Logo class="logo" base_url={{ page.base_url }} />
|
||||
<nav class="cd-navbar nav-links">
|
||||
<NavLinks />
|
||||
<ThemeSwitch class="themeswitch" text={{ false }} />
|
||||
</nav>
|
||||
<nav class="nav-extra">
|
||||
<NavExtra />
|
||||
</nav>
|
||||
<PopButton
|
||||
target="navMobile"
|
||||
title="Show menu"
|
||||
class="cd-toggle-sidebar cd-text-button"
|
||||
>Menu</PopButton>
|
||||
</div>
|
||||
</section>
|
19
docs/theme/Page.jinja
vendored
Normal file
19
docs/theme/Page.jinja
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
<Layout
|
||||
title={{ page.title }}
|
||||
description={{ page.description }}
|
||||
class={{ meta.get('class', 'cd-page') }}
|
||||
>
|
||||
<NavTop></NavTop>
|
||||
<div class="page-wrapper">
|
||||
<NavGlobal></NavGlobal>
|
||||
<main id="main" class="page prose">{{ content }}</main>
|
||||
<NavLocal></NavLocal>
|
||||
</div>
|
||||
<PrevNext
|
||||
curr={{ page }}
|
||||
prev={{ page.prev_page }}
|
||||
next={{ page.next_page }}
|
||||
/>
|
||||
<NavMobile></NavMobile>
|
||||
<Footer></Footer>
|
||||
</Layout>
|
10
docs/theme/PageSingle.jinja
vendored
Normal file
10
docs/theme/PageSingle.jinja
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<Layout
|
||||
title={{ page.title }}
|
||||
description={{ page.description }}
|
||||
class={{ meta.get('class', 'cd-page-single') }}
|
||||
>
|
||||
<NavTop />
|
||||
<main>{{ content }}</main>
|
||||
<NavMobile />
|
||||
<Footer />
|
||||
</Layout>
|
26
docs/theme/PrevNext.jinja
vendored
Normal file
26
docs/theme/PrevNext.jinja
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
{#def curr, prev, next #}
|
||||
|
||||
<nav {{ attrs.render(class="cd-prevnext", data_component="PrevNext") }}>
|
||||
{% if prev.url -%}
|
||||
<a href="{{ prev.url }}" class="prev">
|
||||
<i>←</i>
|
||||
<div>
|
||||
<div class="section">
|
||||
{{ prev.section or "Previous" if prev.section != curr.section else "Previous" }}
|
||||
</div>
|
||||
<div class="title">{{ prev.title }}</div>
|
||||
</div>
|
||||
</a>
|
||||
{%- endif %}
|
||||
{% if next.url -%}
|
||||
<a href="{{ next.url }}" class="next">
|
||||
<div>
|
||||
<div class="section">
|
||||
{{ next.section or "Next" if next.section != curr.section else "Next" }}
|
||||
</div>
|
||||
<div class="title">{{ next.title }}</div>
|
||||
</div>
|
||||
<i>→</i>
|
||||
</a>
|
||||
{%- endif %}
|
||||
</nav>
|
61
docs/theme/SocialCard.jinja
vendored
Normal file
61
docs/theme/SocialCard.jinja
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
{#def page #}
|
||||
<Layout
|
||||
title={{ page.title }}
|
||||
description={{page.description }}
|
||||
>
|
||||
<style>
|
||||
body {
|
||||
background-color: black;
|
||||
}
|
||||
.sc1 {
|
||||
width: 1200px;
|
||||
height: 630px;
|
||||
margin: 0;
|
||||
font-family: SF Pro Display, system-ui, sans-serif;
|
||||
color: white;
|
||||
background-image: linear-gradient(to bottom, #404faa, #0068b2);
|
||||
}
|
||||
.sc1__wrapper {
|
||||
position: absolute;
|
||||
inset: 60px 90px 90px 60px;
|
||||
}
|
||||
.sc1__wrapper > * {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
max-width: 1060px;
|
||||
}
|
||||
.sc1__logo {
|
||||
top: 0;
|
||||
height: 50px;
|
||||
}
|
||||
.sc1__section {
|
||||
top: 150px;
|
||||
line-height: 1;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
font-size: 22px;
|
||||
width: 600px;
|
||||
}
|
||||
.sc1__title {
|
||||
top: 180px;
|
||||
line-height: 1;
|
||||
font-weight: bold;
|
||||
font-size: 68px;
|
||||
}
|
||||
.sc1__description {
|
||||
bottom: 0;
|
||||
line-height: 1.4;
|
||||
font-weight: normal;
|
||||
font-size: 22px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<article class="sc1">
|
||||
<div class="sc1__wrapper">
|
||||
<img class="sc1__logo" src="/static/img/jinjax-logo-w.png" />
|
||||
<h2 class="sc1__section">{{ page.section }}</h2>
|
||||
<h1 class="sc1__title">{{ page.title | utils.widont }}</h1>
|
||||
<div class="sc1__description">{{ page.description | utils.widont }}</div>
|
||||
</div>
|
||||
</article>
|
||||
</Layout>
|
24
docs/theme/Source.jinja
vendored
Normal file
24
docs/theme/Source.jinja
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
{# def url: str, label: str = "" #}
|
||||
{% do attrs.set(href=url, target="_blank") %}
|
||||
{% set icon = url.replace("http://", "").replace("https://", "").split(".")[0] %}
|
||||
|
||||
<a {{ attrs.render(class="cd-source", data_component="Source") }}>
|
||||
<div class="cd-source__icon">
|
||||
{% if icon == "github" -%}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. --><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
|
||||
{% elif icon == "gitlab" -%}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. --><path d="M503.5 204.6L502.8 202.8L433.1 21.02C431.7 17.45 429.2 14.43 425.9 12.38C423.5 10.83 420.8 9.865 417.9 9.57C415 9.275 412.2 9.653 409.5 10.68C406.8 11.7 404.4 13.34 402.4 15.46C400.5 17.58 399.1 20.13 398.3 22.9L351.3 166.9H160.8L113.7 22.9C112.9 20.13 111.5 17.59 109.6 15.47C107.6 13.35 105.2 11.72 102.5 10.7C99.86 9.675 96.98 9.295 94.12 9.587C91.26 9.878 88.51 10.83 86.08 12.38C82.84 14.43 80.33 17.45 78.92 21.02L9.267 202.8L8.543 204.6C-1.484 230.8-2.72 259.6 5.023 286.6C12.77 313.5 29.07 337.3 51.47 354.2L51.74 354.4L52.33 354.8L158.3 434.3L210.9 474L242.9 498.2C246.6 500.1 251.2 502.5 255.9 502.5C260.6 502.5 265.2 500.1 268.9 498.2L300.9 474L353.5 434.3L460.2 354.4L460.5 354.1C482.9 337.2 499.2 313.5 506.1 286.6C514.7 259.6 513.5 230.8 503.5 204.6z"/></svg>
|
||||
{%- else -%}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. --><path d="M439.55 236.05L244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
|
||||
{%- endif %}
|
||||
</div>
|
||||
<div class="cd-source__repo">
|
||||
<span class="cd-source__label">{{ label or url.split("/", 3)[-1] }}</span>
|
||||
<ul class="cd-source__facts">
|
||||
<li data-fact="version" hidden></li>
|
||||
<li data-fact="stars" hidden></li>
|
||||
<li data-fact="forks" hidden></li>
|
||||
<li data-fact="numrepos" hidden></li>
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
123
docs/theme/Source.js
vendored
Normal file
123
docs/theme/Source.js
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
const ATTR_FACT = "data-fact";
|
||||
const CLASS_FACTS = "cd-source__facts";
|
||||
const CLASS_FACTS_VISIBLE = `${CLASS_FACTS}--visible`;
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
document.querySelectorAll('[data-component="Source"]').forEach(showFacts);
|
||||
});
|
||||
|
||||
function showFacts(node) {
|
||||
function renderFacts(facts) {
|
||||
Array.from(node.querySelectorAll(`[${ATTR_FACT}]`))
|
||||
.forEach(function(node) {
|
||||
const name = node.getAttribute(ATTR_FACT);
|
||||
if (facts[name]) {
|
||||
node.removeAttribute("hidden");
|
||||
node.innerText = facts[name];
|
||||
}
|
||||
});
|
||||
|
||||
node.querySelector(`.${CLASS_FACTS}`).classList.add(CLASS_FACTS_VISIBLE);
|
||||
}
|
||||
|
||||
getSourceFacts(node.href, renderFacts);
|
||||
}
|
||||
|
||||
function getSourceFacts(url, callback) {
|
||||
const key = `Source:${url}`;
|
||||
let facts = sessionStorage.getItem(key);
|
||||
if (facts) {
|
||||
callback(JSON.parse(facts));
|
||||
return;
|
||||
}
|
||||
|
||||
fetchSourceFacts(url)
|
||||
.then((facts) => {
|
||||
if (facts && Object.keys(facts).length) {
|
||||
sessionStorage.setItem(key, JSON.stringify(facts));
|
||||
callback(facts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function fetchJSON(url) {
|
||||
return fetch(url)
|
||||
.then(response => response.json())
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function fetchSourceFacts(url) {
|
||||
/* Try to match GitHub repository */
|
||||
let match = url.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);
|
||||
if (match) {
|
||||
const [, user, repo] = match;
|
||||
return fetchSourceFactsFromGitHub(user, repo);
|
||||
}
|
||||
|
||||
/* Try to match GitLab repository */
|
||||
match = url.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i);
|
||||
if (match) {
|
||||
const [, base, slug] = match;
|
||||
return fetchSourceFactsFromGitLab(base, slug);
|
||||
}
|
||||
|
||||
/* Fallback */
|
||||
return null;
|
||||
}
|
||||
|
||||
function fetchSourceFactsFromGitLab(base, project) {
|
||||
const url = `https://${base}/api/v4/projects/${encodeURIComponent(project)}`
|
||||
|
||||
fetchJSON(url)
|
||||
.then(function({ star_count, forks_count }) {
|
||||
return {
|
||||
stars: star_count,
|
||||
forks: forks_count,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function fetchSourceFactsFromGitHub (user, repo) {
|
||||
if (typeof repo === "undefined") {
|
||||
return fetchSourceFactsFromGitHubOrg(user);
|
||||
} else {
|
||||
return fetchSourceFactsFromGitHubRepo(user, repo);
|
||||
}
|
||||
}
|
||||
|
||||
function fetchSourceFactsFromGitHubOrg(user) {
|
||||
const url = `https://api.github.com/users/${user}`
|
||||
|
||||
fetchJSON(url)
|
||||
.then(function(data) {
|
||||
return {
|
||||
numrepos: data.public_repos,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function fetchSourceFactsFromGitHubRepo(user, repo) {
|
||||
const url = `https://api.github.com/repos/${user}/${repo}`
|
||||
|
||||
const release = fetchJSON(`${url}/releases/latest`)
|
||||
.then((data) => {
|
||||
return {
|
||||
version: data.tag_name,
|
||||
};
|
||||
});
|
||||
|
||||
const info = fetchJSON(url)
|
||||
.then((data) => {
|
||||
return {
|
||||
stars: data.stargazers_count,
|
||||
forks: data.forks_count,
|
||||
};
|
||||
});
|
||||
|
||||
return Promise.all([release, info])
|
||||
.then(([release, info]) => {
|
||||
return { ...release, ...info };
|
||||
});
|
||||
}
|
6
docs/theme/Test.jinja
vendored
Normal file
6
docs/theme/Test.jinja
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE html><html>
|
||||
<head><MetaTags page={{ page }} /></head><body class="prose">
|
||||
|
||||
{{ content }}
|
||||
|
||||
</body></html>
|
36
docs/theme/ThemeSwitch.jinja
vendored
Normal file
36
docs/theme/ThemeSwitch.jinja
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
{#def text=true #}
|
||||
|
||||
<button {{ attrs.render(
|
||||
class="cd-theme-switch",
|
||||
data_component="ThemeSwitch",
|
||||
title="Toggle light & dark mode",
|
||||
aria_label="auto",
|
||||
aria_live="polite",
|
||||
) }}>
|
||||
<svg
|
||||
class="sun-and-moon"
|
||||
aria-hidden="true"
|
||||
stroke-linecap="round"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle class="sun" cx="12" cy="12" r="6" mask="url(#moon-mask)"></circle>
|
||||
<g class="sun-beams">
|
||||
<line x1="12" y1="1" x2="12" y2="3" />
|
||||
<line x1="12" y1="21" x2="12" y2="23" />
|
||||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
|
||||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
|
||||
<line x1="1" y1="12" x2="3" y2="12" />
|
||||
<line x1="21" y1="12" x2="23" y2="12" />
|
||||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
|
||||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
|
||||
</g>
|
||||
<mask class="moon" id="moon-mask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white" />
|
||||
<circle cx="24" cy="10" r="6"></circle>
|
||||
</mask>
|
||||
</svg>
|
||||
{% if text -%}
|
||||
<span class="light-text">Light</span>
|
||||
<span class="dark-text">Dark</span>
|
||||
{%- endif %}
|
||||
</button>
|
41
docs/theme/ThemeSwitch.js
vendored
Normal file
41
docs/theme/ThemeSwitch.js
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
import { on } from "./jxui.js";
|
||||
|
||||
const SEL_TARGET = ".cd-theme-switch";
|
||||
const STORAGE_KEY = "theme";
|
||||
|
||||
const DARK = "dark";
|
||||
const LIGHT = "light";
|
||||
const theme = {value: getColorPreference()};
|
||||
|
||||
reflectPreference();
|
||||
on("click", SEL_TARGET, onClick);
|
||||
// sync with system changes
|
||||
window
|
||||
.matchMedia("(prefers-color-scheme: dark)")
|
||||
.addEventListener("change", ({matches:isDark}) => {
|
||||
theme.value = isDark ? DARK : LIGHT
|
||||
setPreference()
|
||||
});
|
||||
|
||||
function onClick (event, target) {
|
||||
if (target.matches("[disabled]")) return;
|
||||
theme.value = theme.value === LIGHT ? DARK : LIGHT;
|
||||
setPreference();
|
||||
}
|
||||
function setPreference () {
|
||||
localStorage.setItem(STORAGE_KEY, theme.value);
|
||||
reflectPreference();
|
||||
}
|
||||
function reflectPreference () {
|
||||
const value = getColorPreference ();
|
||||
if (value === DARK) {
|
||||
document.documentElement.classList.add(DARK);
|
||||
document.documentElement.classList.remove(LIGHT);
|
||||
} else {
|
||||
document.documentElement.classList.add(LIGHT);
|
||||
document.documentElement.classList.remove(DARK);
|
||||
}
|
||||
}
|
||||
function getColorPreference () {
|
||||
return localStorage.getItem(STORAGE_KEY);
|
||||
}
|
45
docs/theme/Toc.jinja
vendored
Normal file
45
docs/theme/Toc.jinja
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
{# def toc, page #}
|
||||
|
||||
{% macro render_page(url, title) %}
|
||||
{% if url != "/" -%}
|
||||
<div class="page {{ 'active' if page.url == url else '' }}">
|
||||
<a href="{{ url }}#">{{ title }}</a>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{% macro render_collapsable(title, children) %}
|
||||
<details open>
|
||||
{% if title %}<summary>{{ title }}</summary>{% endif %}
|
||||
{{ render_children(children) }}
|
||||
</details>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{% macro render_section(title, children) %}
|
||||
<section open>
|
||||
{% if title %}<h2>{{ title }}</h2>{% endif %}
|
||||
{{ render_children(children) }}
|
||||
</section>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{% macro render_children(children, collapsable=True) %}
|
||||
{%- for url, title, sub_children in children %}
|
||||
{% if sub_children -%}
|
||||
{% if collapsable -%}
|
||||
{{ render_collapsable(title, sub_children) }}
|
||||
{%- else -%}
|
||||
{{ render_section(title, sub_children) }}
|
||||
{%- endif %}
|
||||
{%- else -%}
|
||||
{{ render_page(url, title) }}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<div {{ attrs.render(class="cd-toc", data_component="Toc") }}>
|
||||
{{ render_children(toc, collapsable=False) }}
|
||||
</div>
|
21
docs/theme/TocPage.jinja
vendored
Normal file
21
docs/theme/TocPage.jinja
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{#def page_toc, max_depth=3 #}
|
||||
|
||||
{% macro render_sub_items(pages) %}
|
||||
{%- for section in pages %}
|
||||
<li class="indent-{{ section.level }}">
|
||||
<a href="#{{ section.id }}"><span>{{ section.name }}</span></a>
|
||||
</li>
|
||||
{% if section.level <= max_depth -%}
|
||||
{{ render_sub_items(section.children) }}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
{% endmacro %}
|
||||
|
||||
<ul {{ attrs.render(class="cd-toc-page", data_component="TocPage") }}>
|
||||
{%- for section in page_toc %}
|
||||
<li class="indent-{{ section.level }}">
|
||||
<a href="#{{ section.id }}"><span>{{ section.name }}</span></a>
|
||||
</li>
|
||||
{{ render_sub_items(section.children) }}
|
||||
{%- endfor %}
|
||||
</ul>
|
97
docs/theme/TocPage.js
vendored
Normal file
97
docs/theme/TocPage.js
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
import { on } from "./jxui.js";
|
||||
|
||||
const ACTIVE = "active";
|
||||
const SEL_BACKTOTOP = ".cd-back-to-top"
|
||||
const SEL_PAGETOC = ".cd-toc-page"
|
||||
const SEL_TARGET = `${SEL_PAGETOC} a`;
|
||||
const SEL_ACTIVE = `${SEL_TARGET}.${ACTIVE}`;
|
||||
const SEL_PAGE = "#main.page";
|
||||
const SEL_SECTIONS = `${SEL_PAGE} section[id]`;
|
||||
const DESKTOP_THRESHOLD = 1024;
|
||||
|
||||
on("click", SEL_TARGET, handleClick);
|
||||
on("click", SEL_BACKTOTOP, backToTop);
|
||||
|
||||
function handleClick(event, target) {
|
||||
removeHighlight();
|
||||
setTimeout(function () { updateHighlight(target) }, 10);
|
||||
}
|
||||
|
||||
function updateHighlight (elem) {
|
||||
if (window.innerWidth > DESKTOP_THRESHOLD && !elem?.classList.contains(ACTIVE)) {
|
||||
removeHighlight();
|
||||
if (!elem) return;
|
||||
elem.classList.add(ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
function removeHighlight () {
|
||||
document.querySelectorAll(SEL_ACTIVE).forEach(function (node) {
|
||||
node.classList.remove(ACTIVE);
|
||||
});
|
||||
}
|
||||
|
||||
function resetNavPosition () {
|
||||
var pagetoc = document.querySelector(SEL_TOC);
|
||||
pagetoc?.scroll({ top: 0 });
|
||||
}
|
||||
|
||||
export function backToTop () {
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
resetNavPosition();
|
||||
}
|
||||
|
||||
export function scrollSpy() {
|
||||
const sections = Array.from(document.querySelectorAll(SEL_SECTIONS));
|
||||
|
||||
function matchingNavLink(elem) {
|
||||
if (!elem) return;
|
||||
var index = sections.indexOf(elem);
|
||||
|
||||
var match;
|
||||
while (index >= 0 && !match) {
|
||||
var sectionId = sections[index].getAttribute("id");
|
||||
if (sectionId) {
|
||||
match = document.querySelector(`${SEL_PAGETOC} [href="#${sectionId}"]`);
|
||||
}
|
||||
index--;
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
function belowBottomHalf(i) {
|
||||
return i.boundingClientRect.bottom > (i.rootBounds.bottom + i.rootBounds.top) / 2;
|
||||
}
|
||||
|
||||
function prevElem(elem) {
|
||||
var index = sections.indexOf(elem);
|
||||
if (index <= 0) {
|
||||
return null;
|
||||
}
|
||||
return sections[index - 1];
|
||||
}
|
||||
|
||||
const PAGE_LOAD_BUFFER = 1000;
|
||||
|
||||
function navHighlight(entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (entry.isIntersecting) {
|
||||
updateHighlight(matchingNavLink(entry.target));
|
||||
} else if (entry.time >= PAGE_LOAD_BUFFER && belowBottomHalf(entry)) {
|
||||
updateHighlight(matchingNavLink(prevElem(entry.target)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const observer = new IntersectionObserver(navHighlight, {
|
||||
threshold: 0,
|
||||
rootMargin: "0% 0px -95% 0px"
|
||||
});
|
||||
|
||||
sections.forEach(function (elem) {
|
||||
observer.observe(elem);
|
||||
})
|
||||
observer.observe(document.querySelector(SEL_PAGE));
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", scrollSpy);
|
Loading…
Add table
Add a link
Reference in a new issue