Compare commits
59 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1261e55c4a | ||
|
|
8cf676f049 | ||
|
|
e0415e0f66 | ||
|
|
09ba589a00 | ||
|
|
1de4aa798c | ||
|
|
51b4c7ca97 | ||
|
|
de2d06d3a1 | ||
|
|
6bd35e5160 | ||
|
|
458dc41147 | ||
|
|
e8a54bd396 | ||
|
|
b9975435c2 | ||
|
|
9f179b1ead | ||
|
|
7db03ad35e | ||
|
|
11921aa07a | ||
|
|
ec88d58e05 | ||
|
|
9fa33e81c2 | ||
|
|
1b1e4dc154 | ||
|
|
4421378529 | ||
|
|
c7a3fe9412 | ||
|
|
5e0f482db1 | ||
|
|
fbc488cc95 | ||
|
|
69f69be5e4 | ||
|
|
4b4425a2d9 | ||
|
|
f7abb6bf42 | ||
|
|
6e1cdf4018 | ||
|
|
a3ec22a70a | ||
|
|
3aade4630b | ||
|
|
06f0c739df | ||
|
|
c4d21b72ea | ||
|
|
aac22735e4 | ||
|
|
a1db08f32e | ||
|
|
fa0b34c3c2 | ||
|
|
2b2edc7505 | ||
|
|
5b0ff60ac8 | ||
|
|
69119f347d | ||
|
|
d1f405bde1 | ||
|
|
0871b22709 | ||
|
|
a31d6ac095 | ||
|
|
f6f7bd7115 | ||
|
|
95d04f7a0e | ||
|
|
7d58c330a6 | ||
|
|
2537e4d5af | ||
|
|
0fbe169815 | ||
|
|
dd37f2ea40 | ||
|
|
7c1143befc | ||
|
|
cff4e8c8ee | ||
|
|
9bc2a55251 | ||
|
|
b1e129ed6e | ||
|
|
bc94fb954c | ||
|
|
8491b0f751 | ||
|
|
2eb1170992 | ||
|
|
b042f43cdd | ||
|
|
1ca6266464 | ||
|
|
6fea770e71 | ||
|
|
d399f510b7 | ||
|
|
54e74a0f04 | ||
|
|
4e9e16b735 | ||
|
|
12494bf0f0 | ||
|
|
8b0a086d37 |
58
.forgejo/workflows/docs.yml
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
name: Deploy Docs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install uv
|
||||
run: |
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
||||
|
||||
- name: Install Python 3.12 via uv
|
||||
run: |
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
uv python install 3.12
|
||||
|
||||
- name: Build site
|
||||
run: |
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
uv venv --python 3.12 /tmp/venv
|
||||
. /tmp/venv/bin/activate
|
||||
python --version
|
||||
uv pip install zensical
|
||||
uv pip install -e .
|
||||
python3 main.py
|
||||
zensical build --clean
|
||||
|
||||
- name: Deploy to pages branch
|
||||
run: |
|
||||
set -e
|
||||
git config user.name "forgejo-actions"
|
||||
git config user.email "forgejo-actions@noreply.local"
|
||||
|
||||
git fetch origin pages
|
||||
git worktree add /tmp/pages-deploy origin/pages
|
||||
cd /tmp/pages-deploy
|
||||
|
||||
git rm -rf --ignore-unmatch .
|
||||
cp -r "$GITHUB_WORKSPACE"/site/* .
|
||||
cp "$GITHUB_WORKSPACE"/site/.[!.]* . 2>/dev/null || true
|
||||
|
||||
git add .
|
||||
if ! git diff --staged --quiet; then
|
||||
git commit -m "deploy: zensical build from ${GITHUB_SHA::7}"
|
||||
git push origin HEAD:pages
|
||||
else
|
||||
echo "No changes to deploy"
|
||||
fi
|
||||
env:
|
||||
GITHUB_WORKSPACE: ${{ github.workspace }}
|
||||
GITHUB_SHA: ${{ github.sha }}
|
||||
29
.github/workflows/docs.yml
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
name: Documentation
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
jobs:
|
||||
deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/configure-pages@v6
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
- run: pip install zensical
|
||||
- run: zensical build --clean
|
||||
- uses: actions/upload-pages-artifact@v5
|
||||
with:
|
||||
path: site
|
||||
- uses: actions/deploy-pages@v5
|
||||
id: deployment
|
||||
174
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
PASSWORD.txt
|
||||
.hermes
|
||||
codedb.snapshot
|
||||
|
||||
# Old build artifacts (now in site/)
|
||||
/404.html
|
||||
/index.html
|
||||
/search.json
|
||||
/sitemap.xml
|
||||
/objects.inv
|
||||
TODO.md
|
||||
36
.kimi-homepage-beauty-task.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Homepage Beauty Upgrade — Kimi Task
|
||||
|
||||
## MANDATORY INPUT
|
||||
Read first: `/home/a/w/up/docs/zensical-theme-plan.md`
|
||||
|
||||
## Verified constraints (do not violate)
|
||||
- `zensical.toml` is correct and must not be modified.
|
||||
- Source homepage is `docs/index.md`.
|
||||
- Theme entrypoint is `docs/stylesheets/extra.css`.
|
||||
- JS layer is `docs/javascripts/extra.js`.
|
||||
- Override dir is `overrides/`, but prior full-page overrides caused broken builds. Do NOT replace full templates.
|
||||
- Toolbar/code-block icons must remain usable and legible.
|
||||
- Output must be additive, reversible, and contributor-safe.
|
||||
|
||||
## Goal
|
||||
Make the homepage much more beautiful using the documented theme prompt, adapted for Zensical.
|
||||
Focus on the homepage (`docs/index.md` + `docs/stylesheets/extra.css`).
|
||||
Keep the consciousness/awakening tone and multi-contributor friendly structure.
|
||||
|
||||
## Requirements
|
||||
- Fancier typography system, spacing, and front-page composition.
|
||||
- More polished hero treatment and lead paragraph.
|
||||
- Beautiful list and CTA styling.
|
||||
- Additive changes only to CSS/JS and markup classes.
|
||||
- Preserve all behavior helpers (reduced motion, scroll reveal, cursor glow opt-in).
|
||||
- Include a short review summary of every changed file.
|
||||
|
||||
## Do NOT
|
||||
- Edit `zensical.toml`.
|
||||
- Add template overrides without explicit confirmation.
|
||||
- Import heavy frameworks or dependencies.
|
||||
|
||||
## Deliverable
|
||||
- Exact files changed
|
||||
- Short diff summary
|
||||
- Preview/review instructions
|
||||
37
.kimi-premium-homepage-task.md
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Premium Interactive Homepage — Kimi Task
|
||||
|
||||
## Read first
|
||||
- `/home/a/w/up/docs/zensical-theme-plan.md`
|
||||
|
||||
## Hard constraints
|
||||
- Do NOT edit `zensical.toml`
|
||||
- Do NOT replace full templates in `overrides/` — prior full-page overrides broke the build
|
||||
- Keep toolbar/code-block icons legible
|
||||
- Keep reduced-motion safe
|
||||
- Keep JS small and contributor-safe
|
||||
|
||||
## Goal
|
||||
Add a more premium interactive feel to the homepage.
|
||||
Tone: futuristic + nature-themed, calm consciousness/awakening vibe.
|
||||
|
||||
## Required additions
|
||||
1. Animated borders and shadows:
|
||||
- Gentle iridescent/pastel animated borders on hero and contribution card
|
||||
- Soft moving shadow/glow effects, not harsh glows
|
||||
- Use CSS keyframes, respect `prefers-reduced-motion: reduce`
|
||||
2. More homepage elements:
|
||||
- Add 2–3 small content blocks with nice styling, simple class names, easy for contributors to edit
|
||||
- Keep markdown-friendly
|
||||
3. Images/media:
|
||||
- Add optimized image placeholders or nature-themed image blocks
|
||||
- If video is included, make it lazy-load and optional (no autoplay, no heavy bundle)
|
||||
4. Overrides:
|
||||
- If you need template changes, use SMALL additive partials only
|
||||
- Do NOT add a full `main.html` or `footer.html` override
|
||||
5. CTA refinement:
|
||||
- Make the contribution section feel more inviting with subtle hover micro-animations
|
||||
|
||||
## Deliverable
|
||||
- Exact files changed
|
||||
- Short diff summary
|
||||
- Review/preview instructions
|
||||
1
.python-version
Normal file
|
|
@ -0,0 +1 @@
|
|||
3.12
|
||||
811
404.html
|
|
@ -1,811 +0,0 @@
|
|||
|
||||
<!doctype html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
<meta name="description" content="A living guide for awakening consciousness — practices, teachings, and community for the journey upward">
|
||||
|
||||
|
||||
<meta name="author" content="aja">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="icon" href="/assets/images/favicon.png">
|
||||
<meta name="generator" content="zensical-0.0.44">
|
||||
|
||||
|
||||
|
||||
<title>Tree of Ascension Docs</title>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/assets/stylesheets/modern/main.fba56155.min.css">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/assets/stylesheets/modern/palette.dfe2e883.min.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
|
||||
<style>:root{--md-text-font:"Inter";--md-code-font:"JetBrains Mono"}</style>
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/stylesheets/extra.css">
|
||||
|
||||
<script>__md_scope=new URL("/",location),__md_scope.pathname.endsWith("/")||(__md_scope=new URL(__md_scope.pathname+"/",location)),__md_hash=e=>[...e].reduce(((e,t)=>(e<<5)-e+t.charCodeAt(0)),0),__md_get=(e,t=localStorage,_=__md_scope)=>JSON.parse(t.getItem(_.pathname+"."+e)),__md_set=(e,t,_=localStorage,a=__md_scope)=>{try{_.setItem(a.pathname+"."+e,JSON.stringify(t))}catch(e){}},document.documentElement.setAttribute("data-platform",navigator.platform)</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
window.TOA_ACTION_POINTS_ENABLED =
|
||||
true;
|
||||
window.TOA_KEEP_IN_TOUCH_ENDPOINT =
|
||||
"https://subscribe.krystl.org/api/subscribe";
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="green" data-md-color-accent="teal">
|
||||
|
||||
|
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
||||
<label class="md-overlay" for="__drawer" aria-label="Navigation"></label>
|
||||
<div data-md-component="skip">
|
||||
|
||||
<a href="#__skip" class="md-skip">
|
||||
Skip to content
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<header class="md-header md-header--shadow" data-md-component="header">
|
||||
<nav class="md-header__inner md-grid" aria-label="Header">
|
||||
<a href="/" title="Tree of Ascension Docs" class="md-header__button md-logo" aria-label="Tree of Ascension Docs" data-md-component="logo">
|
||||
|
||||
<img src="/assets/images/tree-ad-logo.svg" alt="Tree of Ascension Docs">
|
||||
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer" aria-label="Navigation">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-menu" viewBox="0 0 24 24"><path d="M4 5h16M4 12h16M4 19h16"/></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Tree of Ascension Docs
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="none" data-md-color-scheme="default" data-md-color-primary="green" data-md-color-accent="teal" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
|
||||
|
||||
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg>
|
||||
</label>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="none" data-md-color-scheme="slate" data-md-color-primary="green" data-md-color-accent="teal" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
|
||||
|
||||
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-moon" viewBox="0 0 24 24"><path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401"/></svg>
|
||||
</label>
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-header__button md-icon" for="__search" aria-label="Search">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-search" viewBox="0 0 24 24"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg>
|
||||
</label>
|
||||
<div class="md-search" data-md-component="search" role="dialog" aria-label="Search">
|
||||
<button type="button" class="md-search__button">
|
||||
Search
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="md-header__source">
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
</header>
|
||||
|
||||
<div class="md-container" data-md-component="container">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a href="/" title="Tree of Ascension Docs" class="md-nav__button md-logo" aria-label="Tree of Ascension Docs" data-md-component="logo">
|
||||
|
||||
<img src="/assets/images/tree-ad-logo.svg" alt="Tree of Ascension Docs">
|
||||
|
||||
</a>
|
||||
Tree of Ascension Docs
|
||||
</label>
|
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-leaf" viewBox="0 0 24 24"><path d="M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10"/><path d="M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Home
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
|
||||
|
||||
|
||||
|
||||
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
|
||||
|
||||
|
||||
<div class="md-nav__link md-nav__container">
|
||||
<a href="/practices/" class="md-nav__link ">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13.5 5.5c1.09 0 2-.92 2-2a2 2 0 0 0-2-2c-1.11 0-2 .88-2 2 0 1.08.89 2 2 2M9.89 19.38l1-4.38L13 17v6h2v-7.5l-2.11-2 .61-3A7.3 7.3 0 0 0 19 13v-2c-1.91 0-3.5-1-4.31-2.42l-1-1.58c-.4-.62-1-1-1.69-1-.31 0-.5.08-.81.08L6 8.28V13h2V9.58l1.79-.7L8.19 17l-4.9-1-.4 2z"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Practices
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
<label class="md-nav__link " for="__nav_2" id="__nav_2_label" tabindex="">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
|
||||
<label class="md-nav__title" for="__nav_2">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
|
||||
|
||||
Practices
|
||||
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/practices/daily-sadhana/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 4c1.11 0 2 .89 2 2s-.89 2-2 2-2-.89-2-2 .9-2 2-2m9 12v-2c-2.24 0-4.16-.96-5.6-2.68l-1.34-1.6A1.98 1.98 0 0 0 12.53 9H11.5c-.61 0-1.17.26-1.55.72l-1.34 1.6C7.16 13.04 5.24 14 3 14v2c2.77 0 5.19-1.17 7-3.25V15l-3.88 1.55c-.67.27-1.12.95-1.12 1.66C5 19.2 5.8 20 6.79 20H9v-.5a2.5 2.5 0 0 1 2.5-2.5h3c.28 0 .5.22.5.5s-.22.5-.5.5h-3c-.83 0-1.5.67-1.5 1.5v.5h7.21c.99 0 1.79-.8 1.79-1.79 0-.71-.45-1.39-1.12-1.66L14 15v-2.25c1.81 2.08 4.23 3.25 7 3.25"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Daily Sadhana
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/practices/digital-wellness/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.62 10.79a15.1 15.1 0 0 0 6.59 6.59l2.2-2.2a1 1 0 0 1 1-.25 11.4 11.4 0 0 0 3.59.57 1 1 0 0 1 1 1V20a1 1 0 0 1-1 1A17 17 0 0 1 3 4a1 1 0 0 1 1-1h3.5a1 1 0 0 1 1 1 11.4 11.4 0 0 0 .57 3.57 1 1 0 0 1-.25 1m12.89-3.86-1.42-1.42L15 8.59l-2.29-2.3-1.42 1.42 3.71 3.7Z"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Digital Wellness
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/practices/grounding-in-nature/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4.5 11A1.5 1.5 0 0 0 6 9.5 1.5 1.5 0 0 0 4.5 8 1.5 1.5 0 0 0 3 9.5 1.5 1.5 0 0 0 4.5 11m17.67-1.83c0-3.87-3.13-7-7-7a7 7 0 0 0-7 7c0 3.47 2.52 6.33 5.83 6.89V20H6v-3h1v-4a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v4h1v5h16v-2h-3v-3.88a7 7 0 0 0 6.17-6.95"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Grounding in Nature
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/practices/nourishing-the-body/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 10c2 3-3 12-5 12s-2-1-3-1-1 1-3 1-7-9-5-12 5-3 7-2V5C5.38 8.07 4.11 3.78 4.11 3.78S6.77.19 11 5V3h2v5c2-1 5-1 7 2"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Nourishing the Body
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/practices/spiritual-hygiene/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.5 9.63c-.19-2.79-1.32-5.51-3.44-7.63A12.25 12.25 0 0 0 8.5 9.63c1.29.68 2.47 1.56 3.5 2.63a14.2 14.2 0 0 1 3.5-2.63M12 15.45C9.85 12.17 6.18 10 2 10c0 10 9.32 11.89 10 12 .68-.12 10-2 10-12-4.18 0-7.85 2.17-10 5.45"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Spiritual Hygiene
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
|
||||
|
||||
|
||||
|
||||
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
|
||||
|
||||
|
||||
<div class="md-nav__link md-nav__container">
|
||||
<a href="/strategies/" class="md-nav__link ">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 22H5v-2h14zM13 2c-1.25 0-2.42.62-3.11 1.66L7 8l2 2 2.06-1.37c.44-.31 1.08-.19 1.39.27.02.03.05.06.05.1.3.59.19 1.3-.28 1.77l-4.8 4.8c-.55.56-.55 1.46.01 2.01.26.26.62.42.99.42H17V6a4 4 0 0 0-4-4"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Strategies
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
|
||||
<label class="md-nav__title" for="__nav_3">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
|
||||
|
||||
Strategies
|
||||
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/strategies/collective-awakening/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 17q.86 0 1.45.6t.58 1.4L14 22l-7-2v-9h1.95l7.27 2.69q.78.31.78 1.12 0 .47-.34.82t-.86.37H13l-1.75-.67-.33.94L13 17zM16 3.23Q17.06 2 18.7 2q1.36 0 2.3 1t1 2.3q0 1.03-1 2.46t-1.97 2.39T16 13q-2.08-1.89-3.06-2.85t-1.97-2.39T10 5.3q0-1.36.97-2.3t2.34-1q1.6 0 2.69 1.23M.984 11H5v11H.984z"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Collective Awakening
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/strategies/community-sovereignty/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3.69 9.12a.88.88 0 0 0-.65-.28c-.41 0-.72.19-.92.58s-.15.76.17 1.11q1.77 1.59 2.25 2.25c.41.56.61 1.38.61 2.44 0 1.31.5 2.28 1.5 2.95.56.44 1.17.77 1.85.99v-3.89c0-.94-.33-1.72-.96-2.35m8.92.05c-.62.62-.96 1.39-.96 2.3v3.93c.96-.34 1.76-.87 2.42-1.57.65-.7.98-1.47.98-2.41 0-1.13.19-1.94.57-2.44.09-.16.26-.36.53-.61.23-.25.47-.49.71-.71.23-.21.46-.43.68-.65l.33-.28a.9.9 0 0 0 .28-.66c0-.28-.09-.53-.28-.73s-.42-.3-.72-.3-.5.09-.69.28M12 20c.69 0 1.36-.09 2-.28v-3.57c0-.59-.18-1.05-.59-1.49Q12.795 14 12 14c-.53 0-1 .2-1.38.61-.4.39-.62.85-.62 1.45v3.66c.64.19 1.31.28 2 .28M9 8.5c0 .83-.67 1.5-1.5 1.5S6 9.33 6 8.5 6.67 7 7.5 7 9 7.67 9 8.5m9 0c0 .83-.67 1.5-1.5 1.5S15 9.33 15 8.5 15.67 7 16.5 7s1.5.67 1.5 1.5m-4.5-3c0 .83-.67 1.5-1.5 1.5s-1.5-.67-1.5-1.5S11.17 4 12 4s1.5.67 1.5 1.5m0 5.5c0 .83-.67 1.5-1.5 1.5s-1.5-.67-1.5-1.5.67-1.5 1.5-1.5 1.5.67 1.5 1.5"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Community Sovereignty
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/strategies/digital-sovereignty/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 1 3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5zm0 6c1.4 0 2.8 1.1 2.8 2.5V11c.6 0 1.2.6 1.2 1.3v3.5c0 .6-.6 1.2-1.3 1.2H9.2c-.6 0-1.2-.6-1.2-1.3v-3.5c0-.6.6-1.2 1.2-1.2V9.5C9.2 8.1 10.6 7 12 7m0 1.2c-.8 0-1.5.5-1.5 1.3V11h3V9.5c0-.8-.7-1.3-1.5-1.3"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Digital Sovereignty
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/strategies/finding-purpose/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14.19 14.19 6 18l3.81-8.19L18 6m-6-4A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 8.9a1.1 1.1 0 0 0-1.1 1.1 1.1 1.1 0 0 0 1.1 1.1 1.1 1.1 0 0 0 1.1-1.1 1.1 1.1 0 0 0-1.1-1.1"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Finding Your Purpose
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/contributing/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-heart-handshake" viewBox="0 0 24 24"><path d="M19.414 14.414C21 12.828 22 11.5 22 9.5a5.5 5.5 0 0 0-9.591-3.676.6.6 0 0 1-.818.001A5.5 5.5 0 0 0 2 9.5c0 2.3 1.5 4 3 5.5l5.535 5.362a2 2 0 0 0 2.879.052 2.12 2.12 0 0 0-.004-3 2.124 2.124 0 1 0 3-3 2.124 2.124 0 0 0 3.004 0 2 2 0 0 0 0-2.828l-1.881-1.882a2.41 2.41 0 0 0-3.409 0l-1.71 1.71a2 2 0 0 1-2.828 0 2 2 0 0 1 0-2.828l2.823-2.762"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Contributing
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary" aria-label="On this page">
|
||||
|
||||
|
||||
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-content" data-md-component="content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<article class="md-content__inner md-typeset">
|
||||
|
||||
<h1>404 - Not found</h1>
|
||||
|
||||
</article>
|
||||
</div>
|
||||
|
||||
|
||||
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
|
||||
|
||||
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
|
||||
</div>
|
||||
|
||||
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-circle-arrow-up" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m16 12-4-4-4 4M12 16V8"/></svg>
|
||||
Back to top
|
||||
</button>
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="md-footer">
|
||||
|
||||
|
||||
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
|
||||
<div class="md-copyright__highlight">
|
||||
Copyright © 2026 The authors
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="md-copyright__badges">
|
||||
<span class="md-copyright__zensical">
|
||||
Built with
|
||||
<a href="https://zensical.org/" target="_blank" rel="noopener">
|
||||
Zensical
|
||||
</a>
|
||||
</span>
|
||||
<a href="https://grebedoc.dev" class="md-copyright__grebedoc" title="served by Grebedoc">
|
||||
<img src="https://grebedoc.dev/88x31.gif" alt="served by Grebedoc" style="image-rendering: pixelated; height: 31px; width: 88px;">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script id="__config" type="application/json">{"annotate":null,"base":"/","features":["announce.dismiss","content.action.edit","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.top","navigation.tracking","search.highlight"],"search":"/assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":null}</script>
|
||||
|
||||
|
||||
<script src="/assets/javascripts/bundle.6e5f0216.min.js"></script>
|
||||
|
||||
<script src="/javascripts/extra.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
155
LICENSE
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
|
||||
Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.
|
||||
|
||||
Using Creative Commons Public Licenses
|
||||
|
||||
Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.
|
||||
|
||||
Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors.
|
||||
|
||||
Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public.
|
||||
|
||||
Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License
|
||||
|
||||
By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
|
||||
|
||||
Section 1 – Definitions.
|
||||
|
||||
a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
|
||||
|
||||
b. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
|
||||
|
||||
c. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
|
||||
|
||||
d. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
|
||||
|
||||
e. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
|
||||
|
||||
f. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
|
||||
|
||||
g. Licensor means the individual(s) or entity(ies) granting rights under this Public License.
|
||||
|
||||
h. NonCommercial means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange.
|
||||
|
||||
i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
|
||||
|
||||
j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
|
||||
|
||||
k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
|
||||
|
||||
Section 2 – Scope.
|
||||
|
||||
a. License grant.
|
||||
|
||||
1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
|
||||
|
||||
A. reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and
|
||||
|
||||
B. produce and reproduce, but not Share, Adapted Material for NonCommercial purposes only.
|
||||
|
||||
2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
|
||||
|
||||
3. Term. The term of this Public License is specified in Section 6(a).
|
||||
|
||||
4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
|
||||
|
||||
5. Downstream recipients.
|
||||
A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
|
||||
|
||||
B. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
|
||||
|
||||
6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
|
||||
|
||||
b. Other rights.
|
||||
|
||||
1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
|
||||
|
||||
2. Patent and trademark rights are not licensed under this Public License.
|
||||
|
||||
3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes.
|
||||
|
||||
Section 3 – License Conditions.
|
||||
|
||||
Your exercise of the Licensed Rights is expressly made subject to the following conditions.
|
||||
|
||||
a. Attribution.
|
||||
|
||||
1. If You Share the Licensed Material, You must:
|
||||
|
||||
A. retain the following if it is supplied by the Licensor with the Licensed Material:
|
||||
|
||||
i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
|
||||
|
||||
ii. a copyright notice;
|
||||
|
||||
iii. a notice that refers to this Public License;
|
||||
|
||||
iv. a notice that refers to the disclaimer of warranties;
|
||||
|
||||
v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
|
||||
|
||||
B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
|
||||
|
||||
C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
|
||||
|
||||
For the avoidance of doubt, You do not have permission under this Public License to Share Adapted Material.
|
||||
|
||||
2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
|
||||
|
||||
3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
|
||||
|
||||
Section 4 – Sui Generis Database Rights.
|
||||
|
||||
Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
|
||||
|
||||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only and provided You do not Share Adapted Material;
|
||||
|
||||
b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and
|
||||
|
||||
c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
|
||||
For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
|
||||
|
||||
Section 5 – Disclaimer of Warranties and Limitation of Liability.
|
||||
|
||||
a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.
|
||||
|
||||
b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.
|
||||
|
||||
c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
|
||||
|
||||
Section 6 – Term and Termination.
|
||||
|
||||
a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
|
||||
|
||||
b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
|
||||
|
||||
1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
|
||||
|
||||
2. upon express reinstatement by the Licensor.
|
||||
|
||||
For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
|
||||
|
||||
c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
|
||||
|
||||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
|
||||
|
||||
Section 7 – Other Terms and Conditions.
|
||||
|
||||
a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
|
||||
|
||||
b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
|
||||
|
||||
Section 8 – Interpretation.
|
||||
|
||||
a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
|
||||
|
||||
b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
|
||||
|
||||
c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
|
||||
|
||||
d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
|
||||
|
||||
Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.
|
||||
|
||||
Creative Commons may be contacted at creativecommons.org.
|
||||
3
README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# up
|
||||
|
||||
Collective wiki on practical steps we can take to raise consciousness and support freedom for humanity
|
||||
194
_extensions/wikilinks.py
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
"""
|
||||
Python-Markdown extension: converts [[Wikilinks]] to standard Markdown links.
|
||||
|
||||
Mirrors the behavior of mkdocs-ezlinks-plugin's WikiLinkScanner, but as a
|
||||
pure Markdown preprocessor (no MkDocs plugin API needed). Zensical handles
|
||||
the resulting links natively.
|
||||
|
||||
Syntax:
|
||||
[[Page Name]] → [Page Name](/page-name/)
|
||||
[[Page Name|Display Text]] → [Display Text](/page-name/)
|
||||
[[Page Name#anchor]] → [Page Name](/page-name/#anchor)
|
||||
[[Page Name#anchor|Text]] → [Text](/page-name/#anchor)
|
||||
![[image.png]] → 
|
||||
|
||||
Tolaria-compatible: when the vault root is the project root, links like
|
||||
``[[docs/contributing/index]]`` are stripped of the ``docs/`` prefix and
|
||||
converted to root-relative URLs (e.g. ``/contributing/``) that work from
|
||||
any page regardless of depth.
|
||||
|
||||
Code blocks (fenced and inline) are skipped — wiki links inside them pass
|
||||
through unchanged.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from markdown.preprocessors import Preprocessor
|
||||
from markdown.extensions import Extension
|
||||
|
||||
|
||||
# Regex for a wiki link. Borrowed from mkdocs-ezlinks-plugin's
|
||||
# WikiLinkScanner with minor adjustments.
|
||||
_WIKILINK_RE = re.compile(
|
||||
r"""
|
||||
(?P<image>\!?) # optional ! for image embeds
|
||||
\[\[ # opening [[
|
||||
(?P<link>[^#\|\]]*?) # target (everything before #, |, or ]])
|
||||
(?:\#(?P<anchor>[^\|\]]+)?)? # optional #anchor
|
||||
(?:\|(?P<text>[^\]]+)?)? # optional |display text
|
||||
\]\] # closing ]]
|
||||
""",
|
||||
re.VERBOSE,
|
||||
)
|
||||
|
||||
# Match fenced code blocks or inline code spans (single capture group).
|
||||
_CODE_RE = re.compile(
|
||||
r"(```.*?```|`[^`\n]+`)",
|
||||
re.DOTALL,
|
||||
)
|
||||
|
||||
# Prefix to strip from Tolaria-generated links when the vault root is
|
||||
# the project root (so links look like [[docs/foo/bar]]).
|
||||
_DOCS_PREFIX = "docs/"
|
||||
|
||||
|
||||
def _slugify(text: str) -> str:
|
||||
"""Convert a human page name into a filename slug.
|
||||
|
||||
Mirrors ezlinks: lowercase, spaces → hyphens, strip unsupported chars.
|
||||
Keeps forward slashes for subdirectory paths, dots for extensions, and CJK.
|
||||
"""
|
||||
slug = text.strip().lower()
|
||||
slug = re.sub(r"\s+", "-", slug)
|
||||
# Keep: word chars, hyphens, dots, forward slashes, CJK
|
||||
slug = re.sub(r"[^\w./\u4e00-\u9fff\-]", "", slug)
|
||||
return slug
|
||||
|
||||
|
||||
def _url_from_link(link: str) -> str:
|
||||
"""Convert a wiki link target to a root-relative URL.
|
||||
|
||||
Handles Tolaria-style full paths: strips ``docs/`` prefix,
|
||||
removes ``.md`` extension, collapses ``/index`` suffixes,
|
||||
slugifies each component, and prepends ``/``.
|
||||
"""
|
||||
raw = link.strip()
|
||||
|
||||
# Strip .md extension
|
||||
raw = re.sub(r"\.md$", "", raw, flags=re.IGNORECASE)
|
||||
|
||||
# Strip docs/ prefix (Tolaria vault root = project root)
|
||||
if raw.lower().startswith(_DOCS_PREFIX):
|
||||
raw = raw[len(_DOCS_PREFIX) :]
|
||||
|
||||
# Collapse trailing /index — section index pages resolve to the dir
|
||||
raw = re.sub(r"/index$", "", raw)
|
||||
|
||||
if not raw:
|
||||
return "/"
|
||||
|
||||
# Slugify each path component
|
||||
parts = [_slugify(p) for p in raw.split("/") if p]
|
||||
return "/" + "/".join(parts) + "/"
|
||||
|
||||
|
||||
def _display_name(link: str) -> str:
|
||||
"""Derive a human-readable title from a wiki link path.
|
||||
|
||||
``[[docs/contributing/index]]`` → ``Contributing``
|
||||
``[[docs/strategies/collective-awakening]]`` → ``Collective Awakening``
|
||||
``[[Contributing]]`` → ``Contributing``
|
||||
"""
|
||||
raw = link.strip()
|
||||
|
||||
# Strip .md extension
|
||||
raw = re.sub(r"\.md$", "", raw, flags=re.IGNORECASE)
|
||||
|
||||
# Strip docs/ prefix
|
||||
if raw.lower().startswith(_DOCS_PREFIX):
|
||||
raw = raw[len(_DOCS_PREFIX) :]
|
||||
|
||||
parts = [p for p in raw.split("/") if p]
|
||||
if not parts:
|
||||
return link
|
||||
|
||||
# If the last component is "index", use the parent directory name
|
||||
if parts[-1].lower() == "index":
|
||||
name = parts[-2] if len(parts) >= 2 else parts[-1]
|
||||
else:
|
||||
name = parts[-1]
|
||||
|
||||
# Replace hyphens/underscores with spaces, title-case
|
||||
name = name.replace("-", " ").replace("_", " ")
|
||||
return name.title()
|
||||
|
||||
|
||||
class WikilinksPreprocessor(Preprocessor):
|
||||
"""Preprocessor that converts [[wikilinks]] to root-relative [text](/url/)."""
|
||||
|
||||
def run(self, lines: list[str]) -> list[str]:
|
||||
text = "\n".join(lines)
|
||||
|
||||
# Walk through the text, skipping code spans. Use finditer to
|
||||
# extract code regions, then transform wiki links in the gaps.
|
||||
result: list[str] = []
|
||||
cursor = 0
|
||||
for m in _CODE_RE.finditer(text):
|
||||
before = text[cursor : m.start()]
|
||||
if before:
|
||||
result.append(_WIKILINK_RE.sub(self._replace, before))
|
||||
result.append(m.group(0))
|
||||
cursor = m.end()
|
||||
|
||||
tail = text[cursor:]
|
||||
if tail:
|
||||
result.append(_WIKILINK_RE.sub(self._replace, tail))
|
||||
|
||||
return "\n".join(result).split("\n")
|
||||
|
||||
def _replace(self, match: re.Match) -> str:
|
||||
groups = match.groupdict()
|
||||
is_image = groups.get("image") or ""
|
||||
link = groups.get("link") or ""
|
||||
anchor = groups.get("anchor") or ""
|
||||
text = groups.get("text") or (link if is_image else _display_name(link)) or anchor
|
||||
|
||||
if not (link or text or anchor):
|
||||
return match.group(0)
|
||||
|
||||
# Build the href: root-relative URL for pages; relative for images
|
||||
if is_image:
|
||||
# Images: keep filename, strip docs/ prefix, make root-relative
|
||||
raw = link.strip()
|
||||
if raw.lower().startswith(_DOCS_PREFIX):
|
||||
raw = raw[len(_DOCS_PREFIX) :]
|
||||
# Non-image assets might have extensions; keep them
|
||||
href = raw if "." in raw else _slugify(raw)
|
||||
if not href.startswith("/"):
|
||||
href = "/" + href
|
||||
else:
|
||||
href = _url_from_link(link)
|
||||
|
||||
# Append anchor if present
|
||||
if anchor:
|
||||
anchor_slug = _slugify(anchor)
|
||||
if anchor_slug:
|
||||
href = href.rstrip("/") + "#" + anchor_slug
|
||||
|
||||
if is_image:
|
||||
return f""
|
||||
else:
|
||||
return f"[{text}]({href})"
|
||||
|
||||
|
||||
class WikilinksExtension(Extension):
|
||||
"""Register the WikilinksPreprocessor."""
|
||||
|
||||
def extendMarkdown(self, md):
|
||||
# Priority 35: after normalize_whitespace (30), before html_block (20)
|
||||
md.preprocessors.register(WikilinksPreprocessor(md), "wikilinks", 35)
|
||||
|
||||
|
||||
def makeExtension(**kwargs):
|
||||
return WikilinksExtension(**kwargs)
|
||||
93
content-production-playbook.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# Content Production Playbook — Consciousness Garden
|
||||
|
||||
## Purpose
|
||||
Turn a topic list into organized, rich Zensical docs for the awakening/consciousness site.
|
||||
This document is the reusable task brief for any future content-writing run.
|
||||
|
||||
---
|
||||
|
||||
## 1. Inputs required
|
||||
- Topic list (title + one-line intent per topic)
|
||||
- Desired folder hierarchy preference:
|
||||
- `docs/practices/` — guided practices
|
||||
- `docs/teachings/` — longer essays, frameworks
|
||||
- `docs/experiences/` — community stories, experiences
|
||||
- `docs/reference/` — glossaries, diagrams, maps
|
||||
- `docs/about/` — already exists; keep site meta here
|
||||
|
||||
---
|
||||
|
||||
## 2. Research workflow
|
||||
For each topic:
|
||||
1. Run a short Firecrawl/parallel-cli research pass to pull 2–4 high-quality references.
|
||||
2. Favor primary sources, short readable articles, and non-copyright-restricted diagrams.
|
||||
3. If the topic is technical or structural, prefer diagrammatic explanation.
|
||||
|
||||
---
|
||||
|
||||
## 3. Content standards
|
||||
- **Tone**: calm, grounded, inviting — not performative spirituality.
|
||||
- **Length**: 300–900 words per page unless the topic clearly demands more.
|
||||
- **Structure per post**:
|
||||
- 1–3 sentence intro hook
|
||||
- 3–6 body sections with headings
|
||||
- 1 closing reflection or practice prompt
|
||||
- 1 related link into another page in the same hierarchy
|
||||
- **Accessibility**: readable line length, alt text on images, reduced-motion safe animations.
|
||||
|
||||
---
|
||||
|
||||
## 4. Zensical features to use
|
||||
- Admonitions: `!!! note`, `!!! warning`
|
||||
- Collapsibles: `???` for optional depth
|
||||
- Code/math only when genuinely clarifying a model or practice
|
||||
- Mermaid diagrams: flowcharts, mindmaps, or journey maps when a concept benefits from visual structure
|
||||
- `markdown="1"` for figures/hero-style images
|
||||
- Keep internal links relative to `docs/` paths
|
||||
|
||||
---
|
||||
|
||||
## 5. Images & media
|
||||
- Prefer lightweight PNG/SVG or optimized JPEG.
|
||||
- If video is added:
|
||||
- Use a poster image
|
||||
- Do not autoplay
|
||||
- Prefer HTML5 `<video controls preload="none">`
|
||||
- For diagrams:
|
||||
- Mermaid first
|
||||
- If Mermaid is unsuitable, generate a simple SVG and embed it
|
||||
|
||||
---
|
||||
|
||||
## 6. Hierarchy rules
|
||||
- Keep the tree shallow wherever possible: prefer `docs/practices/grounding.md` over deep nesting.
|
||||
- Add an `index.md` to each section folder only if it adds navigational value.
|
||||
- Avoid duplicate topics — search `docs/` with ripgrep before creating a new page.
|
||||
|
||||
---
|
||||
|
||||
## 7. Linking policy
|
||||
- Every new page should link to:
|
||||
- 1 nearby related page
|
||||
- 1 higher-level hub or index if available
|
||||
- Use human-readable anchor text.
|
||||
- Do not create orphan pages.
|
||||
|
||||
---
|
||||
|
||||
## 8. Review checklist
|
||||
- [ ] Build succeeds with `./.venv/bin/zensical build`
|
||||
- [ ] Images render at reasonable size
|
||||
- [ ] Internal links resolve in `site/search.json`
|
||||
- [ ] Tone consistent with existing homepage
|
||||
- [ ] No broken anchors in markdown
|
||||
- [ ] Reduced-motion styles remain intact
|
||||
|
||||
---
|
||||
|
||||
## 9. Output convention
|
||||
When producing posts from this playbook, return:
|
||||
1. New file paths and folder tree
|
||||
2. 1–3 sentence rationale for hierarchy choice per page
|
||||
3. List of new internal links created
|
||||
4. Any generated assets (`docs/assets/images/*`, `docs/assets/diagrams/*`)
|
||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 3.1 MiB After Width: | Height: | Size: 3.1 MiB |
|
Before Width: | Height: | Size: 2.9 MiB After Width: | Height: | Size: 2.9 MiB |
|
Before Width: | Height: | Size: 2.5 MiB After Width: | Height: | Size: 2.5 MiB |
|
Before Width: | Height: | Size: 6.7 MiB After Width: | Height: | Size: 6.7 MiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 291 KiB After Width: | Height: | Size: 291 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 220 KiB |
|
Before Width: | Height: | Size: 677 KiB After Width: | Height: | Size: 677 KiB |
223
docs/contributing/index.md
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
---
|
||||
title: Contributing
|
||||
icon: lucide/heart-handshake
|
||||
---
|
||||
|
||||
# Contributing to Tree of Ascension Docs
|
||||
|
||||
Welcome! This guide will get you from zero to making your first edit or new post contribution to Tree of Ascension Docs.
|
||||
|
||||
> **🔒 Registration is currently closed.** Self-registration of new contributor accounts are not available at this moment. If you'd like to get involved, solve the puzzle below to reveal the contact email and request access.
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Request access
|
||||
|
||||
<div class="captcha-game" style="background:linear-gradient(135deg,#f0f7f2,#e5f0e8);border-radius:16px;padding:1.5rem 1.8rem;margin:1.2rem 0 1.8rem;text-align:center;border:1px solid #c8dcd0;">
|
||||
<p style="margin:0 0 1rem;color:#3d6b52;font-weight:650;font-size:1.05rem;">🌱 Click each leaf in order to reveal the contact email:</p>
|
||||
<div id="leaf-container" style="display:flex;gap:0.8rem;justify-content:center;align-items:center;flex-wrap:wrap;"></div>
|
||||
<p id="captcha-hint" style="margin:0.9rem 0 0;font-size:0.85rem;color:#6b8b7a;">Click them from smallest to largest 🌱 → 🌳</p>
|
||||
<div id="captcha-result" style="display:none;margin-top:1rem;padding:0.8rem 1rem;background:white;border-radius:10px;font-size:1.05rem;border:1px dashed #92ad9e;"></div>
|
||||
</div>
|
||||
<script>
|
||||
(function(){
|
||||
if(window._leafCaptchaDone)return;window._leafCaptchaDone=true;
|
||||
var leafTypes=[{e:'🌱'},{e:'🌿'},{e:'🪴'},{e:'🌳'}];
|
||||
// shuffle
|
||||
for(var i=leafTypes.length-1;i>0;i--){var j=Math.floor(Math.random()*(i+1));var t=leafTypes[i];leafTypes[i]=leafTypes[j];leafTypes[j]=t;}
|
||||
var container=document.getElementById('leaf-container');
|
||||
var correct=[]; // will hold positions of 🌱,🌿,🪴,🌳 in shuffled visual order
|
||||
leafTypes.forEach(function(l,pos){
|
||||
if(l.e==='🌱')correct[0]=pos;
|
||||
if(l.e==='🌿')correct[1]=pos;
|
||||
if(l.e==='🪴')correct[2]=pos;
|
||||
if(l.e==='🌳')correct[3]=pos;
|
||||
var s=document.createElement('span');
|
||||
s.textContent=l.e;
|
||||
s.id='leaf-'+pos;
|
||||
s.style.cssText='cursor:pointer;display:inline-flex;align-items:center;justify-content:center;width:56px;height:56px;border-radius:50%;background:#4a8262;color:white;font-size:1.4rem;transition:all 0.3s;user-select:none;';
|
||||
s.onclick=function(){captchaClick(pos);};
|
||||
container.appendChild(s);
|
||||
});
|
||||
var order=[],step=0;
|
||||
function resetAll(){
|
||||
order=[];step=0;
|
||||
for(var i=0;i<4;i++){var p=document.getElementById('leaf-'+i);if(p)p.style.background='#4a8262';}
|
||||
}
|
||||
window.captchaClick=function(i){
|
||||
if(order.indexOf(i)!==-1)return;
|
||||
order.push(i);
|
||||
var p=document.getElementById('leaf-'+i);if(p)p.style.background='#b9a5d7';
|
||||
if(correct[step]===i){step++;
|
||||
if(step===4){
|
||||
var r=document.getElementById('captcha-result');
|
||||
r.innerHTML='📧 <a href=\"mailto:tree.ad@use.startmail.com\">tree.ad@use.startmail.com</a>';
|
||||
r.style.display='block';
|
||||
var h=document.getElementById('captcha-hint');
|
||||
h.textContent='✨ You found it! Send an email to request access.';
|
||||
}
|
||||
}else{
|
||||
resetAll();
|
||||
document.getElementById('captcha-hint').textContent='Not quite — try again! Click smallest to largest 🌱 → 🌿 → 🪴 → 🌳';
|
||||
}
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
|
||||
!!! info "Single article"
|
||||
|
||||
If you just want to contriubute a simple edit or a single article you can send it to the above address and we'll handle adding it to the site for you.
|
||||
|
||||
Once you have access, read on below.
|
||||
|
||||
---
|
||||
|
||||
## 🛠 How it works
|
||||
|
||||
| What | Details |
|
||||
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **Code and file hosting** | [Forgejo](https://forgejo.org) — a friendly, self-hosted git (version control) platform that manages changes and files between many users. Git is a distributed open source tool that lets you work on a folder of files and handles the cases where two users have edited the same file (called merge conflicts). |
|
||||
| **Repo** | [bali.krystl.org/aja/up](https://bali.krystl.org/aja/up) |
|
||||
| **Built with** | [Zensical](https://zensical.org) — turns Markdown files into a beautiful docs site |
|
||||
| **Local editor** | [Tolaria](https://tolaria.dev) — a simple desktop app for editing Markdown with git built in |
|
||||
|
||||
---
|
||||
|
||||
## ✏️ Making your first edit directly on Forgejo (easiest as no local setup required)
|
||||
|
||||
Follow these steps. If you get stuck, the answer is usually just a few clicks away.
|
||||
|
||||
### Step 1 — Open the repo in Forgejo
|
||||
|
||||
Go to **[bali.krystl.org/aja/up](https://bali.krystl.org/aja/up)** and sign in with your account.
|
||||
|
||||
### Step 2 — Create your branch
|
||||
|
||||
Every edit lives on its own branch. A branch is a copy of the code that can be kept independent and later merged. This keeps the main site safe while you work and allows us to review and approve or comment on changes.
|
||||
|
||||
- Click the **branch dropdown** (near the top of the page, it probably says `main` or `master`)
|
||||
- Type a short name for your branch — like `add-meditation-guide` or `fix-typo-daily-sadhana`
|
||||
- Click **"Create branch"**
|
||||
|
||||
You're now on your own copy of the site. Any changes you make stay on this branch until you're ready to share them.
|
||||
|
||||
### Step 3 — Edit a file
|
||||
|
||||
- Browse to the file you want to edit (all content lives in the `docs/` folder)
|
||||
- Click the **pencil icon** (✏️) in the toolbar above the file
|
||||
- Make your changes using [Markdown](https://zensical.org/docs/authoring/markdown/)
|
||||
- Scroll down and write a short commit message — something like `Add breathing exercise section`
|
||||
- Click **"Commit changes"**
|
||||
|
||||
### Step 4 — Open a Pull Request
|
||||
|
||||
When your changes are ready:
|
||||
|
||||
- Go back to the repo homepage
|
||||
- You'll see a banner: _"You pushed to your branch — want to open a pull request?"_
|
||||
- Click **"Compare & pull request"**
|
||||
- Add a title and a short description of what you changed
|
||||
- Click **"Create pull request"**
|
||||
|
||||
A maintainer will review your changes and merge them into the main site. That's it! 🎉
|
||||
|
||||
---
|
||||
|
||||
## 💻 Editing locally (optional)
|
||||
|
||||
If you prefer to work on your own computer:
|
||||
|
||||
### You'll need
|
||||
|
||||
- **[Tolaria](https://tolaria.dev)** — a friendly Markdown editor with git support
|
||||
- You can also use any text editor together with **[git](https://git-scm.com/downloads)** — the version control tool
|
||||
|
||||
### Steps
|
||||
|
||||
```bash
|
||||
|
||||
# 1. Clone the repo
|
||||
git clone https://bali.krystl.org/aja/up.git
|
||||
cd up
|
||||
|
||||
# 2. Create your branch
|
||||
git checkout -b my-edit
|
||||
|
||||
# 3. Open the folder in Tolaria and start editing
|
||||
|
||||
# 4. When done, commit and push
|
||||
git add .
|
||||
git commit -m "Describe your changes"
|
||||
git push -u origin my-edit
|
||||
|
||||
# At this point you'll be asked for your username and password.
|
||||
# You can also set up an SSH key which will mean you don't need to type these every time (you will need to email us your public key)
|
||||
```
|
||||
|
||||
Then follow Step 4 above ("Open a Pull Request") to open your pull request on Forgejo.
|
||||
|
||||
---
|
||||
|
||||
## 🌱 Plant Your Own
|
||||
|
||||
Want to run your own version of this site? You can copy it and publish it under your own domain.
|
||||
|
||||
### Copy the repo
|
||||
|
||||
**Option A — With git (recommended):**
|
||||
|
||||
```bash
|
||||
git clone https://bali.krystl.org/aja/up.git my-own-site
|
||||
cd my-own-site
|
||||
```
|
||||
|
||||
**Option B — Download as ZIP:**
|
||||
|
||||
1. Go to [bali.krystl.org/aja/up](https://bali.krystl.org/aja/up)
|
||||
2. Find the **"Download"** or **"⋯"** menu near the top of the file list
|
||||
3. Choose **"Download ZIP"**
|
||||
4. Unzip it on your computer
|
||||
|
||||
### Set up Zensical
|
||||
|
||||
This site uses [Zensical](https://zensical.org) to build from Markdown. Install it and edit the config:
|
||||
|
||||
```bash
|
||||
# Install Zensical (Python 3.12+ required)
|
||||
pip install zensical
|
||||
|
||||
# Or with uv (recommended):
|
||||
uv add --dev zensical
|
||||
```
|
||||
|
||||
### Make it yours
|
||||
|
||||
Open `zensical.toml` and change:
|
||||
|
||||
```toml
|
||||
site_name = "Your Site Name"
|
||||
site_description = "What your site is about"
|
||||
site_url = "https://your-domain.com"
|
||||
site_author = "You"
|
||||
repo_url = "https://your-forgejo-instance/you/your-repo"
|
||||
```
|
||||
|
||||
Replace `docs/assets/images/tree-ad-logo.svg` with your own logo, then build:
|
||||
|
||||
```bash
|
||||
zensical build --config-file zensical.toml
|
||||
```
|
||||
|
||||
Your site appears in the `site/` folder — upload it to any static host (Netlify, Cloudflare Pages, a VPS, or keep it on Forgejo Pages).
|
||||
|
||||
### Use your own domain
|
||||
|
||||
1. Build the site and upload the `site/` folder to your hosting provider
|
||||
2. Point your domain's DNS to your host (your provider will have instructions)
|
||||
3. Update `site_url` in `zensical.toml` to match
|
||||
|
||||
That's it — you now have your own Zensical-powered knowledge garden.
|
||||
|
||||
---
|
||||
|
||||
Questions? Found a bug? **[Open an issue](https://bali.krystl.org/aja/up/issues)** on the repo.
|
||||
115
docs/contributing/markdown.md
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
---
|
||||
icon: simple/markdown
|
||||
---
|
||||
|
||||
# Markdown in 5min
|
||||
|
||||
## Introduction to Markdown Language
|
||||
|
||||
Markdown is a simple language to build web pages. It is easier to read and write than HTML (the language web browsers read) and so we use it to write articles and have a system called Zensical that will compile your Markdown into HTML. You can use this reference to help you write posts and pages directly in our repository where the source documents for this wiki are held. See [[docs/contributing/index]] for more and check the Zensical docs on authoring for a more complete set of markdown notations you can use with Tree.
|
||||
|
||||
## Headers
|
||||
|
||||
```text
|
||||
# H1 Header
|
||||
## H2 Header
|
||||
### H3 Header
|
||||
#### H4 Header
|
||||
##### H5 Header
|
||||
###### H6 Header
|
||||
```
|
||||
|
||||
## Text formatting
|
||||
|
||||
```text
|
||||
**bold text**
|
||||
*italic text*
|
||||
***bold and italic***
|
||||
~~strikethrough~~
|
||||
`inline code`
|
||||
```
|
||||
|
||||
## Links and images
|
||||
|
||||
```text
|
||||
[Link text](https://example.com)
|
||||
[Link with title](https://example.com "Hover title")
|
||||

|
||||

|
||||
```
|
||||
|
||||
## Lists
|
||||
|
||||
```yaml
|
||||
Unordered:
|
||||
|
||||
- Item 1
|
||||
- Item 2
|
||||
- Nested item
|
||||
|
||||
Ordered:
|
||||
|
||||
1. First item
|
||||
2. Second item
|
||||
3. Third item
|
||||
```
|
||||
|
||||
## Blockquotes
|
||||
|
||||
```text
|
||||
> This is a blockquote
|
||||
> Multiple lines
|
||||
>> Nested quote
|
||||
```
|
||||
|
||||
## Code blocks
|
||||
|
||||
````javascript
|
||||
```javascript
|
||||
function hello() {
|
||||
console.log("Hello, world!");
|
||||
}
|
||||
```;
|
||||
````
|
||||
|
||||
## Tables
|
||||
|
||||
```text
|
||||
| Header 1 | Header 2 | Header 3 |
|
||||
|----------|----------|----------|
|
||||
| Row 1 | Data | Data |
|
||||
| Row 2 | Data | Data |
|
||||
```
|
||||
|
||||
## Horizontal rule
|
||||
|
||||
```text
|
||||
---
|
||||
or
|
||||
***
|
||||
or
|
||||
___
|
||||
```
|
||||
|
||||
## Task lists
|
||||
|
||||
```text
|
||||
- [x] Completed task
|
||||
- [ ] Incomplete task
|
||||
- [ ] Another task
|
||||
```
|
||||
|
||||
## Escaping characters
|
||||
|
||||
```text
|
||||
Use backslash to escape: \* \_ \# \`
|
||||
```
|
||||
|
||||
## Line breaks
|
||||
|
||||
```text
|
||||
End a line with two spaces
|
||||
to create a line break.
|
||||
|
||||
Or use a blank line for a new paragraph.
|
||||
```
|
||||
52
docs/index.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
icon: lucide/leaf
|
||||
comments: true
|
||||
---
|
||||
|
||||
# Tree of Ascension Docs
|
||||
|
||||
## Why Tree of Ascension
|
||||
|
||||
The world can seem so chaotic that we feel we have no way to make an impact. But if we start with ourselves using time honoured [[docs/practices/index]] in our daily life and adopt [[docs/strategies/index]] to work together with other like hearted beings (physical or otherwise), we can certainly bring about peace and a lighter timeline, one day at a time.
|
||||
|
||||
### Action steps
|
||||
|
||||
Many sprouts in this tree have action points hidden inside that you can adopt into your life if you feel resonant. Checking these items will help you feel the satisfaction of making progress. Here's a first one for free! Try checking the box below:
|
||||
|
||||
- [ ] Read the introduction
|
||||
|
||||
## How this site came about
|
||||
|
||||
A small group of us kept having the same kind of conversation. Late nights, voice notes, walls of text — sharing things that had actually moved the needle in our own lives. Practices that stuck. Realizations that rearranged something. Books and teachers and mistakes and breakthroughs.
|
||||
|
||||
At some point we thought: why keep this scattered across chat logs? Let's put it somewhere. Not as experts. Not as a finished thing. Just as what it is — notes from people climbing, passing the lantern back down the trail.
|
||||
|
||||
---
|
||||
|
||||
## What we mean by ascension
|
||||
|
||||
Not floating off into the clouds. Not bypassing the hard stuff. Ascension, the way we talk about it, is waking up _here_. In your actual body, in your actual life, with your actual pain and joy and confusion.
|
||||
|
||||
It's learning to hold more light without burning out. It's noticing when you're running a program that isn't yours — from culture, from family, from fear — and gently putting it down. It goes in layers. You think you've arrived and then the next onion skin peels back and you realize you were just getting started. That's the game. That's the fun of it.
|
||||
|
||||
Some people call it awakening. Some call it remembering. The name doesn't matter much. What matters is that it's possible, it's happening to ordinary people everywhere, and nobody needs permission to begin.
|
||||
|
||||
---
|
||||
|
||||
## Consciousness isn't abstract
|
||||
|
||||
You can feel it. When your mind goes quiet and there's still someone there — aware, alive, unimpressed by the chatter. That's consciousness. Not a concept. It is you, yourself, the light of awareness reading these words.
|
||||
|
||||
Practices — meditation, grounding, fasting, silence, community, sound, service — are just ways of clearing the static so you can hear what was already there. The tree doesn't need to _become_ something. It just needs enough light and water to grow into what it already is.
|
||||
|
||||
---
|
||||
|
||||
## How to use this site
|
||||
|
||||
The [[Practices]] section is where to start. Pick one thing and try it. Not all of them. One. Give it a week.
|
||||
|
||||
The Strategies section is for when a practice opens a door and you want to understand the room you just walked into. Frameworks, context, the bigger picture.
|
||||
|
||||
Everything here is a draft. We update it when we learn something new or when someone points out we got something wrong. If something lands for you — or if it doesn't — we'd love to hear about it.
|
||||
|
||||
- [ ] Mark this sprout complete
|
||||
108
docs/practices/daily-sadhana.md
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
---
|
||||
icon: material/meditation
|
||||
---
|
||||
# Daily Sadhana
|
||||
|
||||
*Sadhana* means daily spiritual practice — not something you do when you have time, but the foundation upon which you build everything else. The best time to practice is first thing in the morning, ideally waking an hour before sunrise. At this hour the energy is quiet, as the world is still asleep. Settling into meditation during the 48 minutes surrounding sunrise lets you ride a moment when the energy is in transition — and your practice can have a far greater impact.
|
||||
|
||||
***
|
||||
|
||||
## Morning routine
|
||||
|
||||
Drinking water on waking helps re-hydrate, as the body hasn't drunk anything for several hours. Warm water, or at least room temperature (not cold) is best.
|
||||
|
||||
Juice of one lemon or lime, 2 or 3 fingers of water, half spoon of bicarbonate of soda/baking soda (food grade, aluminium free) mixed in a tall glass, first thing in the morning helps regulate any excess acidity and re-hydrate.
|
||||
|
||||
## Meditation
|
||||
|
||||
- [ ] Sit quietly for 5 minutes — your bed, a chair, a floor, anywhere
|
||||
- [ ] Notice when the mind wanders and gently return to breath
|
||||
- [ ] Do this every morning for one week
|
||||
|
||||
Start with five minutes. The mind will wander — that's what minds do. The practice is not emptying the mind but noticing when it has drifted and gently returning to the breath. Every return is a rep, and like any muscle, attention strengthens with use.
|
||||
|
||||
You can use meditate on your bed, in the car, on a chair or the floor, a patch of grass — anywhere you can be still.
|
||||
|
||||
### Zen
|
||||
|
||||
The word *zen* traces back through the Chinese *chan* to the Sanskrit *dhyāna*, meaning meditation or deep absorption. The ancient sages studied this state with extraordinary care, and the depth of their insight is something our modern mind can only begin to appreciate. See Patanjali's *Yoga Sutras* if you'd like to go deeper.
|
||||
|
||||
#### Focus
|
||||
|
||||
The mind can rest on many different objects in meditation. We suggest starting with the breath, since it is a simple and direct link to your soul and to the universe — every breath is an exchange between your being and the greater oneness that holds it.
|
||||
|
||||
You can also choose another single point of focus to help the mind settle — a sound (mantra) or a form (yantra). In all, there are 112 techniques for focusing the mind, explored in the ancient text *Vijñāna Bhairava Tantra*.[1](#user-content-fn-1)
|
||||
|
||||
***
|
||||
|
||||
## Gratitude journal
|
||||
|
||||
- [ ] Before bed or first thing, write down 3 specific things you're grateful for
|
||||
- [ ] Do this every day for one week and notice the shift
|
||||
|
||||
Not generic blessings — specific moments. The warmth of sunlight through a window. A conversation that landed. The taste of a ripe fruit.
|
||||
|
||||
Gratitude is the deliberate practice of noticing what is already good, which rewires the brain away from its negativity bias over time.
|
||||
|
||||
## Merit journal
|
||||
|
||||
The merit journal is a practice for reinforcing the virtues in our personality. It can be as simple as noting a smile you offered a stranger on the street or the time you spent truly listening to a friend's concern. By writing down the good you've done, you create a record to reflect upon — especially valuable in the moments before leaving the body at the end of life. Our character is the one thing we carry with us when we depart, so it is well worth the effort to reflect upon and cultivate it.
|
||||
|
||||
- [ ] Write an entry in your merit journal
|
||||
|
||||
***
|
||||
|
||||
## Improvements journal
|
||||
|
||||
This is the inner work few want to do: asking honestly where you are still reactive, and where your character could grow more harmonious and balanced.
|
||||
|
||||
Almost every emotion has its time and place. Sometimes it is good to rest or to feel impatient, and anger can be necessary to provoke action. In general, though, we can soften the distorted forms of these emotions (emotion is energy in motion) and cultivate their positive counterparts instead. Balance is the aim.
|
||||
|
||||
- [ ] Ask yourself: Where am I still carrying anger?
|
||||
- [ ] Ask yourself: What am I afraid of?
|
||||
- [ ] Ask yourself: How can I be more patient today?
|
||||
- [ ] Replace one judgment with kindness today
|
||||
|
||||
To start, pick the one with the most impact, often anger. The goal is not to become perfect — it is to become less impulsive, more available, more unconditionally loving. Starting with yourself is key. Notice your thought patterns and how you speak to yourself. Do you scold yourself over a trivial mistake? How might you extend and deepen your patience toward yourself?
|
||||
|
||||
??? question "A simple evening practice"
|
||||
|
||||
Sit quietly and replay the day. Notice any moment where you contracted — irritation, defensiveness, avoidance. Don't judge the reaction. Just see it. Tomorrow, you'll have another chance. If you like you can journal your reflections and over time you may see just by noticing them things have started to resolve.
|
||||
|
||||
After reviewing the key area you'd like to work on you can use auto-suggestion to improve it.
|
||||
|
||||
***
|
||||
|
||||
## Movement: energy and strength
|
||||
|
||||
The body needs two kinds of movement every day:
|
||||
|
||||
**Energy practice** — yoga, tai chi, qigong, or simple stretching with breath awareness. This moves *prana* (life force) through the channels of the body. Even ten minutes shifts the nervous system from fight-or-flight to rest-and-digest.
|
||||
|
||||
- [ ] Do 10 minutes of energy practice this morning (yoga, stretching, tai chi)
|
||||
- [ ] Do 20 minutes of cardio or strength work today
|
||||
|
||||
**Cardio and strength** — walking briskly, running, bodyweight exercises, lifting. The body evolved to move against resistance. Without it, the mind stagnates too. Cardio comes in two intensities, and both are necessary: low intensity (such as energy practice or gardening) and high intensity (such as running, cycling, swimming, or tennis). High intensity is anything that raises your heart rate and makes you sweat.
|
||||
|
||||
Pair them. Energy practice in the morning to open; strength in the afternoon to ground.
|
||||
|
||||
***
|
||||
|
||||
## Visualization: morning and night
|
||||
|
||||
- [ ] Spend 2 minutes each morning visualizing the future you want — see it as real *now*
|
||||
- [ ] Spend 2 minutes before sleep visualizing the same — feel the gratitude as if it arrived
|
||||
|
||||
This is the practice of orienting the subconscious toward what you are building, so that during the day, you recognize the doors when they appear.
|
||||
|
||||
***
|
||||
|
||||
**Related:** [Finding Your Purpose](../../strategies/finding-purpose.md) — when sadhana meets direction.
|
||||
|
||||
*What practice will you show up for tomorrow?*
|
||||
|
||||
- [ ] Mark this sprout read
|
||||
|
||||
## Footnotes
|
||||
|
||||
1. The *Vijñāna Bhairava Tantra*, a 7th–8th century Kashmir Shaivism text, presents 112 dhāraṇās (meditation techniques) as a dialogue between Bhairava and the goddess Bhairavi, who together personify the interplay between consciousness and energy. [Wikipedia](https://en.wikipedia.org/wiki/Vij%C3%B1%C4%81na_Bhairava_Tantra) [↩](#user-content-fnref-1)
|
||||
70
docs/practices/digital-wellness.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
icon: material/phone-check
|
||||
---
|
||||
|
||||
# Digital Wellness
|
||||
|
||||
<figure class="page-hero">
|
||||
<img src="../assets/images/digital-wellness.jpg" alt="A peaceful nature scene — digital detox in the forest" loading="lazy">
|
||||
<figcaption>Photo by <a href="https://unsplash.com/@lianhao">Lianhao Qu</a> on Unsplash</figcaption>
|
||||
</figure>
|
||||
|
||||
Your attention is the most valuable resource you own. Every notification, every algorithmic feed, every autoplay is designed to extract it. Taking it back is not a luxury — it is a prerequisite for any kind of awakening.
|
||||
|
||||
---
|
||||
|
||||
## The news fast
|
||||
|
||||
Try this: no news for one week. No headlines, no push alerts, no doom-scrolling. The world will continue. The things you actually need to know will reach you through people, not algorithms.
|
||||
|
||||
- [ ] Try a one-week news fast — no headlines, no push alerts, no doom-scrolling
|
||||
|
||||
After a week, notice: is your anxiety lower? Is your attention span longer? Are you more present with the people in front of you?
|
||||
|
||||
!!! note "The 0% horror rule"
|
||||
Zero horror films. Zero true crime. Zero content that feeds fear. Your nervous system does not distinguish between a threat on screen and a threat in the room — the cortisol release is real.
|
||||
|
||||
---
|
||||
|
||||
## Curating what enters your mind
|
||||
|
||||
Replace passive consumption with intentional selection. Build a playlist of media that genuinely brings you joy — films, shows, documentaries that leave you feeling expanded, not depleted.
|
||||
|
||||
- **Music**: only songs where every word is positive. Natural classical, sacred frequency music (432 Hz, 528 Hz), instrumental pieces that create space rather than filling it.
|
||||
- **Images**: keep a few favorite baby animal photos handy — on your phone wallpaper, on the fridge. It sounds simple, but the oxytocin release from cuteness is real and immediate. It's a quick return to heart center when you need it.
|
||||
|
||||
---
|
||||
|
||||
## Screen limits for yourself and family
|
||||
|
||||
Set boundaries you can actually keep:
|
||||
|
||||
- [ScreenZen](https://screenzen.co/) — makes you pause before opening apps, breaking the reflex loop.
|
||||
- [Kids360](https://kids360.app/) — for children's devices, with transparent limits rather than secret surveillance.
|
||||
- No screens in the bedroom. Charge devices in another room.
|
||||
- [ ] Remove or mute one app that drains your attention
|
||||
- [ ] Replace one hour of screen time this week with an outdoor activity
|
||||
|
||||
The point is to cultivate your agency and command over your tech, you should be the one in control.
|
||||
|
||||
---
|
||||
|
||||
## Replacing screen time with life
|
||||
|
||||
For every hour you reclaim from screens:
|
||||
|
||||
- Sit outside and do nothing
|
||||
- Read something printed on paper
|
||||
- Call someone you love
|
||||
- Cook a meal from whole ingredients
|
||||
- Write by hand
|
||||
|
||||
The internet is a tool. When it becomes the environment, you've lost the plot.
|
||||
|
||||
---
|
||||
|
||||
**Related:** [Digital Sovereignty](../../strategies/digital-sovereignty.md) — when wellness meets infrastructure.
|
||||
|
||||
*What's the first app you'll set a limit on today?*
|
||||
|
||||
- [ ] Mark this sprout read
|
||||
76
docs/practices/grounding-in-nature.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
icon: material/nature-people
|
||||
---
|
||||
|
||||
# Grounding in Nature
|
||||
|
||||
<figure class="page-hero">
|
||||
<img src="../assets/images/nature_bathing.jpg" alt="Forest bathing — a person immersed in dappled woodland light" loading="lazy">
|
||||
<figcaption>Photo by Adamu</figcaption>
|
||||
</figure>
|
||||
|
||||
Every moment spent with bare skin on soil, grass, or sand is a reconnection to the electromagnetic field that humans evolved within for hundreds of thousands of years.
|
||||
|
||||
The Earth (whose other names include mother Gaia, Aurora, Aurelia, Tara), is a living being, and we are a small part of her.
|
||||
|
||||
But connecting to the ground, whether that's by contact with our bare feet, using grounding blanket or pad, or even lying down and rolling (one of the best ways to rebalance energy when it gets too high!) we are chemically interacting with our physical Source via ionic exchange.
|
||||
|
||||
Even if we can't physically touch the earth we can use awareness, visualisation and intention to guide our energy body down and root it into the crystalline core of mother Gaia. This crystalline core differs from the iron core of earth and is in a higher dimension.
|
||||
|
||||
!!! info inline end "Coming soon"
|
||||
|
||||
Guided meditation for grounding to mother earth
|
||||
|
||||
---
|
||||
|
||||
## Why ground?
|
||||
|
||||
Modern life separates us from the earth: rubber-soled shoes, elevated buildings, concrete pavements. The simple act of barefoot contact — called _earthing_ or _grounding_ — allows the body to absorb free electrons from the earth's surface. Research has documented reductions in inflammation, improved sleep, and measurable shifts in nervous system function from regular grounding practice.[^1]
|
||||
|
||||
!!! note "Start small"
|
||||
|
||||
Five minutes of bare feet on grass in the morning is enough to begin. You don't need a forest retreat — a patch of lawn, a beach, or even damp soil in a garden works.
|
||||
|
||||
---
|
||||
|
||||
## Sun gazing: reconnecting with light
|
||||
|
||||
Sun gazing is an ancient practice of looking at the sun during the first or last hour of daylight, when UV levels are lower. Start with 10 seconds and never push beyond comfort. The practice is less about the eyes and more about allowing the body's circadian rhythm to realign with natural light cycles.
|
||||
|
||||
!!! warning "Eye safety"
|
||||
|
||||
Tilt you head down and look 2 inches above the Sun, not directly at it. Stop if you feel discomfort and only gradually build up the duration, starting with 10 seconds and working up to 15 minutes over 6 months is a realistic goal. Some yogis look directly at the sun during midday but this is achieved over many years of practice.
|
||||
|
||||
Sit. Breathe. Let the light wash over you. No agenda.
|
||||
|
||||
---
|
||||
|
||||
## Sitting practice: temples, forests, waterfalls
|
||||
|
||||
Find a place where nature is doing its thing without human orchestration — a forest floor, a temple courtyard, beside a waterfall. Looking at the fractal form of nature found in trees, leaves, and the entire environment is highly nourishing for the nervous system. More significantly the energy flow in nature is more balanced and harmonious, whereas buildings and rooms composed of steel, aluminium and electrosmog are dissonant and disturb this flow.
|
||||
|
||||
??? info "Discover more"
|
||||
|
||||
- [ ] See Dan Winter's talks on fractal geometry on YouTube
|
||||
|
||||
Just sit and watch. Notice how the mind, given no task, eventually settles. This is _melukat_ in the Balinese tradition — water purification not just of the body, but of the energetic residue we carry.[^2] Even sitting beside moving water, without entering it, can shift something.
|
||||
|
||||
---
|
||||
|
||||
## Integrating nature time
|
||||
|
||||
The guideline is simple: for every hour on a device, spend an equal hour in direct contact with the natural world. Think of it as restoration and a reward.
|
||||
|
||||
Start tracking it loosely. You may find, as many do, that the nature hours become the ones you crave.
|
||||
|
||||
---
|
||||
|
||||
**Related:** [Nourishing the Body](nourishing-the-body.md) — bringing nature inside through food and materials.
|
||||
|
||||
_What patch of earth will you stand on tomorrow morning?_
|
||||
|
||||
- [ ] Mark this sprout read
|
||||
|
||||
[^1]: Oschman JL, Chevalier G, Brown R. "The effects of grounding (earthing) on inflammation, the immune response, wound healing, and prevention and treatment of chronic inflammatory and autoimmune diseases." *Journal of Inflammation Research*, 2015. [PMC4378297](https://pmc.ncbi.nlm.nih.gov/articles/PMC4378297/)
|
||||
|
||||
[^2]: Melukat is a Balinese Hindu water purification ritual performed at holy springs (*tirta*) to cleanse the body and spirit. [merusaka.com](https://merusaka.com/bali-cultural-experience/bali-sacred-water-melukat-purification-ritual/)
|
||||
19
docs/practices/index.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
icon: material/run
|
||||
---
|
||||
|
||||
# Practices
|
||||
|
||||
Small, doable actions. Each one is something you can try today — no preparation, no expertise, just willingness.
|
||||
|
||||
<div class="grid cards gp-cards-practices" markdown>
|
||||
|
||||
- [:material-nature-people: **Grounding in Nature**](grounding-in-nature.md) Barefoot contact, sun gazing, sitting practice, melukat
|
||||
- [:material-food-apple: **Nourishing the Body**](nourishing-the-body.md) Real food, herbal teas, fasting, natural materials, self-massage
|
||||
- [:material-meditation: **Daily Sadhana**](daily-sadhana.md) Meditation, gratitude, shadow work, movement, visualization
|
||||
- [:material-phone-check: **Digital Wellness**](digital-wellness.md) News fast, screen limits, curating what enters your mind
|
||||
- [:material-spa: **Spiritual Hygiene**](spiritual-hygiene.md) Cleanse your space, set intention, sound as medicine
|
||||
|
||||
</div>
|
||||
|
||||
Pick one. Start there. The rest will unfold.
|
||||
92
docs/practices/nourishing-the-body.md
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
icon: material/food-apple
|
||||
---
|
||||
# Nourishing the Body
|
||||
|
||||
The body is a highly sophisticated ecosystem that responds to everything you place in it, on it, and around it.
|
||||
|
||||
Our focus has been guided towards numbers like calories, steps, BMI (weight and height). These quantitative perspectives can be practical, but they often overlook the more subtle qualitative dimensions of health that can be observed and felt more easily through focused awareness than with measures and scales or lab equipment.
|
||||
|
||||
??? info "Dive deeper"
|
||||
|
||||
```text
|
||||
The body is comprised of a fine balance of elements in different frequencies and states. These are a reflection of the state of the underlying aether at phases and degrees of motion. For instance solid materials are heavy, dense and even though it appears inert, their molecules are actually moving, albeit very slowly. Whereas when these molecules are heated, they undergo a dissolution of the bonds (which are really not a solid thing either, more an electrostatic coupling), and they 'melt' and move from solid to liquid and eventually to a gas and residue (solid aggregate byproduct). If we take more descriptive names to the states we could say the solid "earth" moves through liquid "water" by a process called "fire" and transforms into a gas called "air". Really all these states are part of one all encompassing consciousness and energy, the essence of which is plasma or "aether" as named in Ancient Greek. Modern science disregards this final point, owing to an experiment in 1887 called the Michelson Morley experiment, however this does not actually disprove the existence aether. You can read more about this at Aether Force Blog
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Food from farmers, gardens and your plant pots, not corporations
|
||||
|
||||
Most of what fills supermarket shelves is the product of monopolized supply chains — processed, preserved, and profited from at every step. The alternative is older and simpler: know who grows your food.
|
||||
|
||||
Work with local farmers. Join a CSA (community-supported agriculture). Buy from a neighbor who keeps hens. Trade skills for produce. When you eat food grown by yourself or someone you've spoken to, something shifts — you feel the livingness of the food and the vitality it brings you.
|
||||
|
||||
!!! warning "The supermarket trap"
|
||||
|
||||
```text
|
||||
Nearly every aisle in a conventional supermarket funnels money into a handful of conglomerates. The [documentary on monopolies](https://www.youtube.com/watch?v=nLZV5EesNNI) covers how all the big brand food items are owned by a handful of conglomerates and VC firms and is worth watching to see how it is possible that near everything in your Walgreens or 7 eleven has been engineered for profit and without your best interest or health at heart. You could also see Pam Peeke's fantastic lecture on the Hacked and Hijacked brain on how fast food acts like cocaine on the dopamine centres of the brain, and how to reset via meditation. Start by removing one aisle at a time from your routine and soon you'll feel your taste buds catching up to your desire for healthy organic and fresh natural food and drinks.
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Herbal teas as daily medicine
|
||||
|
||||
Herbal teas are one of the gentlest ways to rebalance the body throughout the day:
|
||||
|
||||
| Time | Tea | Purpose |
|
||||
| --------------- | ------------------------------------------------ | ------------------------- |
|
||||
| Morning | Flower teas (chamomile, jasmine, rose) | Light, opening, uplifting |
|
||||
| After meals | Ginger tea | Digestive fire, warmth |
|
||||
| When agitated | Vata-pacifying (licorice, cinnamon, ashwagandha) | Grounding, calming |
|
||||
| When overheated | Pitta-pacifying (mint, fennel, coriander) | Cooling, soothing |
|
||||
|
||||
Learn your own patterns. The tea that works for someone else may not be yours — experiment gently.
|
||||
|
||||
- [ ] Try a new herbal tea
|
||||
|
||||
***
|
||||
|
||||
## Fasting as reset
|
||||
|
||||
Fasting doesn't need to be extreme to be effective. Start with one day a week of liquids only — fresh juices, soups, herbal teas. From there, try a 24-hour water fast. With guidance, you can work toward a 3-day water fast, which triggers deeper cellular repair processes (autophagy).[1](#user-content-fn-1)
|
||||
|
||||
It's about giving the digestive system the rest it rarely receives in a culture of constant consumption.
|
||||
|
||||
- [ ] Try eating or drinking only fruits (smoothies allowed with coconut water) for 24 hours
|
||||
|
||||
***
|
||||
|
||||
## What touches your skin
|
||||
|
||||
Gradually replace clothing and bed linen with natural, non-toxic materials: organic cotton, linen, hemp, wool. The skin is the largest organ — what it rests against for 8 hours a night matters.
|
||||
|
||||
The same applies to what you put *on* your body. A self oil massage (*abhyanga*) with a simple, chemical-free oil suited to your constitution — or just pure coconut oil — is a daily practice that nourishes skin, calms the nervous system, and reconnects you to your own body with care rather than criticism.
|
||||
|
||||
- [ ] Replace one item of synthetic clothing with a fully natural alternative
|
||||
|
||||
??? info "Hint"
|
||||
|
||||
Start with underwear. A 1993 study found that polyester underwear caused significant (mostly reversible) damage to sperm production in dogs, while cotton had no effect — the cause was electrostatic charge or some other effect from wearing synthetic fabrics.[2](#user-content-fn-2)
|
||||
|
||||
***
|
||||
|
||||
## Small detox steps
|
||||
|
||||
- **Tongue scraping** each morning removes the coating that accumulates overnight.
|
||||
- **Sauna** or sweat lodges help the body release what it's been storing.
|
||||
- **Reduce foods** you already know don't agree with you — you know which ones they are.
|
||||
|
||||
None of this needs to happen overnight. One change, held consistently, reshapes a life.
|
||||
|
||||
***
|
||||
|
||||
**Related:** [Grounding in Nature](grounding-in-nature.md) — where nourishment meets the earth.
|
||||
|
||||
*What's one thing your body has been quietly asking you to change?*
|
||||
|
||||
- [ ] Mark this sprout read
|
||||
|
||||
## Footnotes
|
||||
|
||||
1. Autophagy — the body's cellular cleanup and recycling process — was the subject of Yoshinori Ohsumi's 2016 Nobel Prize in Physiology or Medicine. Fasting is one of the most reliable ways to trigger it. [nobelprize.org](https://www.nobelprize.org/prizes/medicine/2016/ohsumi/facts/) [↩](#user-content-fnref-1)
|
||||
2. Shafik A. "Effect of different types of textile fabric on spermatogenesis: an experimental study." *Urological Research*, 1993. [PMID: 8279095](https://pubmed.ncbi.nlm.nih.gov/8279095/) — Note: this was an animal study (dogs). [↩](#user-content-fnref-2)
|
||||
99
docs/practices/spiritual-hygiene.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
---
|
||||
icon: material/spa
|
||||
---
|
||||
# Spiritual Hygiene
|
||||
|
||||
Just as you wash your body, your space and energy field benefit from regular tending too. Environments hold residue, and your intention shapes what you encounter.
|
||||
|
||||
***
|
||||
|
||||
## Cleansing your space
|
||||
|
||||
- See the [[docs/practices/daily-sadhana]] action items that will also affect your space. The humans in a space have the greatest impact upon its vibration.
|
||||
- Chanting is a very powerful way to raise vibration in a space. You can use any sound you enjoy that connects you to yourself. Chanting in the mind is more powerful than out loud.
|
||||
- [ ] Clear and declutter one space in your home right now
|
||||
- Clean and declutter: every object carries a subtle energetic weight, see [Marie Kondo](https://www.youtube.com/@MarieKondoTV) and [A monk's guide to a clean house and mind](https://www.thezengateway.com/culture/an-interview-with-shoukei-matsumoto-author-of-a-monk-s-guide-to-a-clean-house-and-mind)
|
||||
- Cleaning is extremely important, as any dirt and detritus will repel higher consciousness beings and attract those from the lower realms, just like how if you leave a mess insects will be drawn to it, the same applies to non physical beings. A clean home and a clean heart are pre-requisites to connecting to angelic and divine beings.
|
||||
- Open windows daily and allow light and fresh air to circulate through your space
|
||||
- Remove electronics from the room, or at minimum cover screens
|
||||
- [ ] Try a sound cleansing — ring a brass bell, play a singing bowl, or put on Solfeggio tones for 10 minutes
|
||||
- Use pure frequency: a brass bell with bright tones, a tibetan or crystal singing bowl, download and play a Tarpan music, or Solfeggio tone music in the background on your phone.
|
||||
- Burn natural incense or diffuse pure essential oils (frankincense, sage, palo santo)
|
||||
|
||||
!!! info "Discover more"
|
||||
|
||||
- Healing with Form, Energy and Light by Tenzin Wangyal Rinpoche
|
||||
- Pranic Healing by Master Choa Kok Sui
|
||||
|
||||
??? question "How often should I cleanse?"
|
||||
|
||||
A light daily clearing (open window, intention setting) and a deeper weekly reset (sound, smoke, decluttering) is a sustainable rhythm. After arguments, illness, or visits from heavy energy, cleanse immediately and go outside for a walk.
|
||||
|
||||
***
|
||||
|
||||
## Clearing Sleep Space
|
||||
|
||||
Your bedroom is the most important room to tend. You spend a third of your life there, in a more unconscious and receptive state. Make your bed as soon as you wake up, crumpled sheets create surprisingly discordant energy. It also helps you feel you've achieved something and sets the precedent to take care of yourself and your life.
|
||||
|
||||
Before sleeping you can light a ghee or sattvic oil lamp, being careful it will not be disturbed or near any flammable items. You could keep a shrine or altar with items that make you happy and feel love, that could be family or those who have inspired you who have good character.
|
||||
|
||||
### Intention
|
||||
|
||||
Before sleep, state clearly — aloud or internally:
|
||||
|
||||
> *I invite only energies of the highest light to interact with me. My space is sovereign. My field is clear.*
|
||||
|
||||
- [ ] Set this intention aloud before sleep tonight
|
||||
|
||||
You don't need to believe in guides for this to work. The practice is about setting a boundary and orienting your awareness toward what is loving, clear, and true. Whatever your framework — ancestors, angels, higher self, or simply the clearest version of your own consciousness — the act of calling it in is what matters.
|
||||
|
||||
***
|
||||
|
||||
## Sound as medicine
|
||||
|
||||
The frequencies you surround yourself with shape your nervous system. Consider:
|
||||
|
||||
- Solfeggio tones — a set of frequencies used in alternative healing traditions:[^1]
|
||||
- **432 Hz** — often described as calming and naturally resonant
|
||||
- **528 Hz** — sometimes called the "love frequency" and associated with transformation in alternative medicine circles
|
||||
- **Natural classical** — Debussy, Ravi Shankar — music that creates space rather than filling it
|
||||
- **Kirtan and mantra** — collective chanting that synchronizes heart rates and entrains the group field
|
||||
|
||||
The rule is simple: if a song has a single negative word or message, skip it. The subconscious absorbs everything. Curate your sound environment as carefully as your food.
|
||||
|
||||
- [ ] Try a week of only positive, uplifting music — no negative lyrics
|
||||
|
||||
***
|
||||
|
||||
## Group singing, toning, and joy
|
||||
|
||||
Human voices together are one of the most powerful frequency generators available. Group singing — kirtan, toning, community choirs, or just friends around a fire — synchronizes nervous systems, releases oxytocin, and creates a field of shared vibration that lingers long after the sound stops.
|
||||
|
||||
Pair this with:
|
||||
|
||||
- **Uplifting art** — surround yourself with images that open the heart
|
||||
- **Light-hearted comedy** — laughter is a genuine cleansing practice
|
||||
- **Positive energy events** — gatherings where the purpose is simply to feel good together
|
||||
- **Joy maxxing** is relentlessly choosing what your heart calls you to do, even if you would have been shy or too scared to pursue it normally. It could be wearing that silly hat, or singing and dancing in the rain. Take at least one day a week or one hour a day to really follow your heart!
|
||||
|
||||
***
|
||||
|
||||
## Mass meditations and peace visualization
|
||||
|
||||
When large numbers of people hold the same intention simultaneously, something measurable shifts. A 2017 study of large Transcendental Meditation groups found a 28.4% reduction in murder rates across 206 US urban areas during periods when the practicing group exceeded a critical threshold.[^2] Similar studies have reported reductions in violent crime, traffic fatalities, and drug-related deaths during the same periods.
|
||||
|
||||
Join global mass meditations when they are called. Or gather a small group — even three people — and sit together with the intention of peace and the most positive timeline for humanity.
|
||||
|
||||
Create something tangible to crystallize the intention: a doodle, a piece of art, a short written statement of what that positive timeline looks like *for you*. Make it specific. Make it beautiful. Keep it visible.
|
||||
|
||||
***
|
||||
|
||||
**Related:** [Daily Sadhana](daily-sadhana.md) — spiritual hygiene as daily practice.
|
||||
|
||||
*What's the first thing you'll clear from your bedroom tonight?*
|
||||
|
||||
- [ ] Mark this sprout read
|
||||
|
||||
[^1]: Solfeggio frequencies originate from a medieval hymn to St. John the Baptist and were reinterpreted in the 1970s by Dr. Joseph Puleo as healing tones. While many people find them subjectively calming, there is no rigorous scientific evidence that specific frequencies repair DNA or produce specific physiological effects. A 2019 review noted that most published studies on 432 Hz music are small and preliminary. [scienceinsights.org](https://scienceinsights.org/what-is-528-hz-the-love-frequency-explained/)
|
||||
|
||||
[^2]: Cavanaugh KL, Dillbeck MC. "Field-effects of consciousness: A follow-up study on the reduction of murder rates in large US urban areas." *Journal of Health and Environmental Research*, 2017. The study was conducted by researchers at Maharishi University of Management, the institution founded by the founder of Transcendental Meditation. Results are debated in the wider scientific community. [EurekAlert summary](https://www.eurekalert.org/news-releases/511271)
|
||||
82
docs/strategies/collective-awakening.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
icon: material/hand-heart
|
||||
---
|
||||
|
||||
# Collective Awakening
|
||||
|
||||
<figure class="page-hero">
|
||||
<img src="../assets/images/collective-awakening.jpg" alt="Group of people meditating together in nature at golden hour" loading="lazy">
|
||||
<figcaption>Photo by <a href="https://unsplash.com/@rishikesh_yogpeeth">Rishikesh Yogpeeth</a> on Unsplash</figcaption>
|
||||
</figure>
|
||||
|
||||
Awakening is often described as an individual journey, but it has never been a solo project. Consciousness shifts ripple through groups, communities, and fields — and when enough people hold the same frequency simultaneously, something in the collective field changes.
|
||||
|
||||
---
|
||||
|
||||
## The power of mass intention
|
||||
|
||||
Decades of research on group meditation — particularly large Transcendental Meditation assemblies — has documented correlations between group practice and reductions in crime, violence, and other social stress indicators when a critical mass (roughly the square root of 1% of a population) meditates together.[^1]
|
||||
|
||||
When you join a mass meditation — whether online or in person — you are not just calming your own nervous system. You are contributing to a field. The intention you hold for peace, for the most positive timeline, is not private. It radiates.
|
||||
|
||||
- [ ] Join a mass meditation this month — search online for upcoming global events
|
||||
|
||||
---
|
||||
|
||||
## Creating your own circle
|
||||
|
||||
You don't need to wait for a global event. Gather two or three people and sit together:
|
||||
|
||||
1. **Start with silence** — 5 to 15 minutes of shared stillness
|
||||
2. **State an intention** — "We are here for peace. We are here for the most positive timeline for humanity."
|
||||
3. **Visualize together** — describe, aloud or silently, what that world looks like, feels like, sounds like
|
||||
4. **Close with sound** — a bell, a chant, a simple "om"
|
||||
|
||||
Do it weekly. The consistency matters more than the size.
|
||||
|
||||
---
|
||||
|
||||
## Crystallizing the vision
|
||||
|
||||
Between gatherings, make something tangible:
|
||||
|
||||
- [ ] Create a vision artifact — a doodle, statement, or drawing of the world you want to see
|
||||
- **Doodles or drawings** — what does the peaceful world look like through your eyes?
|
||||
- **Written statements of intent** — short, present-tense declarations: *"Clean water flows freely. Children laugh without fear. Elders are honored. The land is tended."*
|
||||
- **A shared board or album** — where each person contributes their vision of the positive timeline
|
||||
|
||||
These artifacts serve as anchors. When the external world looks chaotic, the images and words you've created together remind you what you are building toward — and that you are building it together.
|
||||
|
||||
---
|
||||
|
||||
## Conscious activism
|
||||
|
||||
Activism doesn't require anger. The most effective campaigns combine awareness with action:
|
||||
|
||||
- **Awareness**: educate your community — host film screenings, share resources, write clearly about what's happening
|
||||
- **Action**: engage with key decision makers — local council members, school boards, community leaders
|
||||
- **Campaigns**: focused efforts on specific issues — stopping a harmful development, protecting green space, defending digital rights
|
||||
|
||||
Do this offline where possible. Face-to-face relationships with decision makers are harder to dismiss than emails. And when you work alongside others in person, the trust built is its own reward.
|
||||
|
||||
---
|
||||
|
||||
## The compass
|
||||
|
||||
Through all of this, hold a simple compass:
|
||||
|
||||
- [ ] Before the next emotional action, ask: Is this arising from love or from fear?
|
||||
- Is it connecting people or dividing them?
|
||||
- Is it building something or only tearing something down?
|
||||
|
||||
Fear-based activism burns out. Love-based activism regenerates. The most radical thing you can do — genuinely radical — is to remain joyful while fighting for what matters.
|
||||
|
||||
---
|
||||
|
||||
**Related:** [Spiritual Hygiene](../practices/spiritual-hygiene.md) — keeping your own field clear so you can contribute cleanly to the collective.
|
||||
|
||||
*What does the most positive timeline look like to you — in one sentence?*
|
||||
|
||||
- [ ] Mark this sprout read
|
||||
|
||||
[^1]: Cavanaugh KL, Dillbeck MC. "Field-effects of consciousness: A follow-up study on the reduction of murder rates in large US urban areas." *Journal of Health and Environmental Research*, 2017. A series of studies from Maharishi University researchers has found correlations between large TM-Sidhi groups and reductions in social stress indicators; the interpretation of these findings is not universally accepted. [EurekAlert summary](https://www.eurekalert.org/news-releases/511271)
|
||||
95
docs/strategies/community-sovereignty.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
---
|
||||
icon: material/crowd
|
||||
---
|
||||
|
||||
# Community Sovereignty
|
||||
|
||||
<figure class="page-hero">
|
||||
<img src="../assets/images/community-sovereignty.jpg" alt="People shopping at a farmers market with fresh produce" loading="lazy">
|
||||
<figcaption>Photo by <a href="https://unsplash.com/@theguccer2100">Spencer Plouzek</a> on Unsplash</figcaption>
|
||||
</figure>
|
||||
|
||||
Sovereignty grows in relationship — with the land, with the people who grow food, with neighbors who share skills, and with networks that operate outside the extractive economy.
|
||||
|
||||
---
|
||||
|
||||
## Food: know your farmer
|
||||
|
||||
Every dollar spent at a supermarket feeds a system designed to concentrate wealth and power. The alternative is older than capitalism: direct relationships with the people who produce what you consume.
|
||||
|
||||
- Join a local CSA (community-supported agriculture)
|
||||
- [ ] Buy from farmers' markets — talk to the people behind the stall
|
||||
- [ ] Trade skills: help with a harvest, offer web design, teach a class
|
||||
- [ ] Grow something yourself, even if it's just herbs on a windowsill
|
||||
|
||||
When your food comes from someone you know, the transaction becomes a relationship. That relationship is the foundation of a parallel economy.
|
||||
|
||||
!!! warning "The monopoly problem"
|
||||
[Watch this](https://www.youtube.com/watch?v=nLZV5EesNNI) to understand how deeply monopolized the food system is. The solution is not to find ethical products within the system — it's to build outside it.
|
||||
|
||||
---
|
||||
|
||||
## Private Members Associations and collectives
|
||||
|
||||
In many jurisdictions, Private Members Associations (PMAs) allow groups to operate outside the regulatory frameworks designed for commercial entities. They are not businesses — they are associations of people exercising their right to associate and self-govern.
|
||||
|
||||
PMAs can be used for:
|
||||
|
||||
- Education cooperatives outside state curricula
|
||||
- Health collectives practicing natural medicine
|
||||
- Legal support networks with aligned professionals
|
||||
- Community asset ownership (land, equipment, housing)
|
||||
|
||||
Research what's possible in your jurisdiction. Find lawyers and politicians with genuine integrity — they exist, often working quietly — who can help push back on overreach in climate policy, health mandates, surveillance expansion, and data center proliferation.
|
||||
|
||||
---
|
||||
|
||||
## Seva: service without expectation
|
||||
|
||||
*Seva* is selfless service — giving without any expectation of return. It is the antidote to the transactional mindset that pervades modern life.
|
||||
|
||||
Start small:
|
||||
|
||||
- [ ] Cook a meal for someone who is struggling
|
||||
- [ ] Sit and listen to someone who is lonely — just listen, no advice
|
||||
- [ ] Clean a section of your local park or river
|
||||
- [ ] Offer your skills (legal, technical, therapeutic) to those who cannot pay
|
||||
|
||||
Do three kind things every week that you tell no one about. The anonymity is part of the practice — it purifies the motivation.
|
||||
|
||||
---
|
||||
|
||||
## Building freedom networks
|
||||
|
||||
Create community links — both offline and online — that support and develop:
|
||||
|
||||
| Domain | What to build |
|
||||
|--------|--------------|
|
||||
| **Education** | Study groups, skill-shares, unschooling collectives |
|
||||
| **Technology** | Local mesh networks, open-source tooling, privacy workshops |
|
||||
| **Health** | Herbal medicine circles, movement groups, mental/emotional/spiritual support pods |
|
||||
| **Legal** | Network of integrity-driven lawyers, know-your-rights workshops |
|
||||
| **Economic** | Barter networks, time banks, local currencies, PMAs |
|
||||
|
||||
The goal is not to secede from society. It is to build parallel structures so robust that when the extractive systems falter, communities don't.
|
||||
|
||||
---
|
||||
|
||||
## Legally minimizing extraction
|
||||
|
||||
Tax avoidance within the law is not evasion — it is resource sovereignty. Learn about:
|
||||
|
||||
- PMAs and trusts for collective asset holding
|
||||
- Agricultural exemptions where applicable
|
||||
- Non-profit structures for community-serving work
|
||||
- Barter and gift economies that operate outside taxable transactions
|
||||
|
||||
Consult aligned professionals. The goal is to keep resources circulating within the community rather than being siphoned upward.
|
||||
|
||||
---
|
||||
|
||||
**Related:** [Digital Sovereignty](./digital-sovereignty.md) — because freedom networks need free infrastructure.
|
||||
|
||||
*Who in your community could you reach out to this week?*
|
||||
|
||||
- [ ] Mark this sprout read
|
||||
71
docs/strategies/digital-sovereignty.md
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
---
|
||||
icon: material/shield-lock
|
||||
---
|
||||
|
||||
# Digital Sovereignty
|
||||
|
||||
Digital sovereignty means owning your own digital life — the hardware, the software, the data, the networks. It is the recognition that every time you use a "free" service, you are the product. Taking back control is not a technical exercise; it is a spiritual one.
|
||||
|
||||
---
|
||||
|
||||
## The hardware you already own
|
||||
|
||||
An old laptop — the one gathering dust — can run Linux perfectly. Modern distributions like MX Linux or Linux Mint breathe new life into aging hardware and free you from operating systems designed to extract data.
|
||||
|
||||
For phones, the path is similar:
|
||||
|
||||
| Device | System | Notes |
|
||||
|--------|--------|-------|
|
||||
| Second-hand Google Pixel | [GrapheneOS](https://grapheneos.org/) | Privacy-hardened Android, no Google services |
|
||||
| Various Android phones | [/e/OS (Murena)](https://murena.com/) | De-googled Android with cloud services |
|
||||
| Various devices | [postmarketOS](https://postmarketos.org/) | True Linux on mobile, still maturing |
|
||||
|
||||
!!! note "Start with the phone"
|
||||
Your phone is the most intimate surveillance device you own. It knows your location, your contacts, your voice, your typing patterns, your sleep schedule. Moving to a de-googled OS is the single highest-impact step you can take.
|
||||
|
||||
---
|
||||
|
||||
## Network sovereignty
|
||||
|
||||
- [ ] Switch your main computer from WiFi to Ethernet
|
||||
- [ ] On your phone: switch 5G to 4G, use airplane mode when not needed
|
||||
- [ ] Install and use a trusted VPN with a clear no-logging policy
|
||||
- [ ] Keep your phone away from your body — not in a pocket, not against your head
|
||||
|
||||
**VPN**: A simple, trusted VPN prevents your internet provider from building a profile of every site you visit. Choose one with a clear no-logging policy and preferably based outside surveillance alliances. Mullvad, Nyx are good. If you want extra privacy pay via Monero.
|
||||
|
||||
**Meshtastic**: When the grid is not your friend, build your own. [Meshtastic](https://meshtastic.org/) lets you create off-grid, encrypted text networks using inexpensive LoRa radios. It's community infrastructure — no cell towers, no subscriptions, no central authority.
|
||||
|
||||
---
|
||||
|
||||
## Erasing your digital footprint
|
||||
|
||||
Move away from Google piece by piece:
|
||||
|
||||
| Instead of | Use |
|
||||
|-----------|-----|
|
||||
| Gmail | [Proton Mail](https://proton.me/mail), self-hosted mail |
|
||||
| Google Drive | [Syncthing](https://syncthing.net/), [Nextcloud](https://nextcloud.com/) |
|
||||
| Google Photos | [Ente](https://ente.com/), local storage shared by Syncthing |
|
||||
| Google Docs | [CryptPad](https://cryptpad.fr/), Libre Office suite |
|
||||
|
||||
The principle is simple: **self-hosted first, local-first, privacy-first**. If your data lives on someone else's computer, it is not your data.
|
||||
|
||||
---
|
||||
|
||||
## Passwords and keys
|
||||
|
||||
- [ ] Install KeePassXC and create your first password database
|
||||
- [ ] Generate unique passwords for every important service
|
||||
- [ ] Get a hardware security key (like a YubiKey) where possible
|
||||
|
||||
Treat your digital keys as carefully as the keys to your home.
|
||||
|
||||
|
||||
---
|
||||
|
||||
**Related:** [Digital Wellness](../../practices/digital-wellness.md) — sovereignty begins with what you consume.
|
||||
|
||||
*What's one service you could migrate away from this month?*
|
||||
|
||||
- [ ] Mark this sprout read
|
||||
75
docs/strategies/finding-purpose.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
icon: material/compass
|
||||
---
|
||||
|
||||
# Finding Your Purpose
|
||||
|
||||
Beyond making a living lies the question that has quietly followed you for years: *why am I really here?* Not your job title. Not your roles. The thing that makes your heart come alive and, in doing so, lifts others up.
|
||||
|
||||
---
|
||||
|
||||
## The passion that was always there
|
||||
|
||||
Your purpose is innate and can be seen in your passions, what you naturally feel drawn to. In childhood these may have been more evident by how you spent your free time. Your soul was born with a particular intention to experience and contribute something to this reality, this can be seen in your natural tendencies and skills or gifts. Meditation or Spiritual Hypnotherapy can be powerful way to discover life's purpose more clearly.
|
||||
|
||||
Ask yourself:
|
||||
|
||||
- [ ] Write down your answer: What would I do if money were not a concern?
|
||||
- [ ] Write down your answer: What challenge have I lived through that I could help others navigate?
|
||||
- What topic could I talk about for hours without tiring?
|
||||
- What makes me feel most alive — and who benefits when I am in that state?
|
||||
|
||||
That last question is often the most direct path. The wound becomes the gift.
|
||||
|
||||
---
|
||||
|
||||
## When suffering becomes service
|
||||
|
||||
Look at the most difficult experience of your life — the one you wouldn't wish on anyone. Now consider: who is going through that right now, alone, with no guide?
|
||||
|
||||
Your experience is not just yours. It is a map that someone else desperately needs. When you offer it — not as a savior but as someone who has walked a similar road — you transform suffering into meaning.
|
||||
|
||||
This is not about becoming a coach or therapist (though it could be). It's about being available: mentoring one person, writing honestly about what you learned, starting a small group, or simply being the person you wish had been there for you.
|
||||
|
||||
---
|
||||
|
||||
## Seva: purpose in action
|
||||
|
||||
Purpose without service becomes self-absorption. *Seva* — selfless service — grounds your gifts in the real world:
|
||||
|
||||
- Cook and deliver meals in your community
|
||||
- Offer your time to simply listen — no advice, no fixing
|
||||
- Clean a park or river without posting about it
|
||||
- Share your skills (legal, technical, therapeutic) with those who cannot afford them
|
||||
|
||||
Do three kind things every week that you tell no one about. The secrecy purifies the motivation. You're not building a brand — you're building a life.
|
||||
|
||||
---
|
||||
|
||||
## The tribe you're building
|
||||
|
||||
Your purpose will attract people. Not everyone — just the ones who resonate with what you're putting into the world. This is your tribe: not a following, but a mutual support network of people moving in the same direction.
|
||||
|
||||
Spend more time with people who are on a positive frequency — those who energize rather than drain. You can still feel compassion for those on a lower frequency, but you are not obligated to be friends with them. Your energy is finite. Spend it where it grows.
|
||||
|
||||
---
|
||||
|
||||
## The daily turn toward purpose
|
||||
|
||||
You don't need to quit your job tomorrow. Start with:
|
||||
|
||||
- [ ] Do one unannounced act of kindness each day this week
|
||||
- One hour a week on the thing that lights you up
|
||||
- One conversation with someone doing what you feel called to do
|
||||
- One small act of service, unannounced
|
||||
- One visualization, morning and night, of the future you are building
|
||||
|
||||
Purpose is a direction you calibrate toward, daily, with each small choice. Which of your daily actions feel aligned with your purpose, and which ones could use a nudge in the right direction?
|
||||
|
||||
---
|
||||
|
||||
**Related:** [Community Sovereignty](./community-sovereignty.md) — purpose expressed through collective action.
|
||||
|
||||
*What challenge have you lived through that someone else needs help with right now?*
|
||||
|
||||
- [ ] Mark this sprout read
|
||||
18
docs/strategies/index.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
icon: material/chess-knight
|
||||
---
|
||||
|
||||
# Strategies
|
||||
|
||||
Big-picture frameworks for when a practice opens a door and you're ready to walk through. These are the patterns, mindsets, and structural shifts — the strategy beneath the tactics.
|
||||
|
||||
<div class="grid cards gp-cards-strategies" markdown>
|
||||
|
||||
- [:material-shield-lock: **Digital Sovereignty**](digital-sovereignty.md) Own your hardware, software, data, and networks
|
||||
- [:material-crowd: **Community Sovereignty**](community-sovereignty.md) Parallel economies, PMAs, seva, freedom networks
|
||||
- [:material-compass: **Finding Your Purpose**](finding-purpose.md) Passion, suffering into service, building your tribe
|
||||
- [:material-hand-heart: **Collective Awakening**](collective-awakening.md) Mass intention, circles, crystallizing the vision
|
||||
|
||||
</div>
|
||||
|
||||
Come back to these. They'll mean something different each time.
|
||||
1180
index.html
16
index.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# _{site title here}_
|
||||
|
||||
<figure class="godspark-hero" markdown="1">
|
||||
<img src="assets/images/hero.jpg" alt="Awakening" />
|
||||
<figcaption>Nature is the oldest teacher of awareness.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p class="intro-lead">
|
||||
A quiet invitation into presence. This is a living space for reigniting the spark inside — not a performance, but a shared practice.
|
||||
</p>
|
||||
|
||||
## How to contribute
|
||||
|
||||
- **Add a reflection** — short notes, practices, or questions
|
||||
- **Plant an idea** — link into new themed pages
|
||||
- **Tend the tone** — kind, grounded edits keep the garden coherent
|
||||
75
main.py
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Generate the Tree of Ascension action-points totals manifest.
|
||||
|
||||
Scans docs/**/*.md for Markdown tasklist items (`- [ ]` / `- [x]`), counts
|
||||
them per page, and writes docs/javascripts/toa-totals.json mapping each
|
||||
page's site URL -> total task count.
|
||||
|
||||
The action-points JS (docs/javascripts/extra.js) fetches this manifest once
|
||||
on first load so nav badges show correct totals BEFORE a user has visited
|
||||
every page. Counts are fully static (known from the Markdown), so this has
|
||||
zero runtime cost — it's a build-time artifact.
|
||||
|
||||
Run before `zensical build`:
|
||||
python3 main.py
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
DOCS = ROOT / "docs"
|
||||
OUT = DOCS / "javascripts" / "toa-totals.json"
|
||||
|
||||
# Matches a Markdown tasklist item: optional indent, list marker, [ ] or [x].
|
||||
TASK_RE = re.compile(r"^\s*[-*+]\s+\[[ xX]\]\s+", re.MULTILINE)
|
||||
|
||||
# Matches fenced code blocks (``` or ~~~), incl. language hint, non-greedy.
|
||||
# These contain tasklist *examples* (e.g. the Markdown reference doc) that render
|
||||
# as plain text, NOT interactive checkboxes — so we strip them before counting.
|
||||
FENCE_RE = re.compile(r"^([ \t]*)(`{3,}|~{3,}).*?\n.*?^\1\2[ \t]*$", re.MULTILINE | re.DOTALL)
|
||||
|
||||
|
||||
def count_tasks(text: str) -> int:
|
||||
"""Count real (interactive) tasklist items, excluding fenced code examples."""
|
||||
stripped = FENCE_RE.sub("", text)
|
||||
return len(TASK_RE.findall(stripped))
|
||||
|
||||
|
||||
def url_for(md_path: Path) -> str:
|
||||
"""Map a docs/*.md path to its built site URL (directory-style URLs).
|
||||
|
||||
docs/index.md -> /
|
||||
docs/practices/index.md -> /practices/
|
||||
docs/practices/daily-sadhana.md-> /practices/daily-sadhana/
|
||||
"""
|
||||
rel = md_path.relative_to(DOCS).with_suffix("")
|
||||
parts = list(rel.parts)
|
||||
if parts and parts[-1] == "index":
|
||||
parts = parts[:-1]
|
||||
path = "/" + "/".join(parts)
|
||||
if not path.endswith("/"):
|
||||
path += "/"
|
||||
return path
|
||||
|
||||
|
||||
def main() -> None:
|
||||
totals: dict[str, int] = {}
|
||||
for md in sorted(DOCS.rglob("*.md")):
|
||||
text = md.read_text(encoding="utf-8")
|
||||
count = count_tasks(text)
|
||||
if count:
|
||||
totals[url_for(md)] = count
|
||||
|
||||
OUT.parent.mkdir(parents=True, exist_ok=True)
|
||||
OUT.write_text(json.dumps(totals, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
||||
print(f"toa-totals: wrote {len(totals)} page(s) -> {OUT.relative_to(ROOT)}")
|
||||
for url, n in sorted(totals.items()):
|
||||
print(f" {url} {n}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
792
markdown/index.html
Normal file
|
|
@ -0,0 +1,792 @@
|
|||
|
||||
<!doctype html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
<meta name="description" content="Tools for a more conscious and free humanity">
|
||||
|
||||
|
||||
<meta name="author" content="aja">
|
||||
|
||||
|
||||
|
||||
<link rel="prev" href="./..">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="icon" href="../assets/images/favicon.png">
|
||||
<meta name="generator" content="zensical-0.0.43">
|
||||
|
||||
|
||||
|
||||
<title>Markdown in 5min - up</title>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/modern/main.fba56155.min.css">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/modern/palette.dfe2e883.min.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
|
||||
<style>:root{--md-text-font:"Inter";--md-code-font:"JetBrains Mono"}</style>
|
||||
|
||||
|
||||
|
||||
<script>__md_scope=new URL("..",location),__md_scope.pathname.endsWith("/")||(__md_scope=new URL(__md_scope.pathname+"/",location)),__md_hash=e=>[...e].reduce(((e,t)=>(e<<5)-e+t.charCodeAt(0)),0),__md_get=(e,t=localStorage,_=__md_scope)=>JSON.parse(t.getItem(_.pathname+"."+e)),__md_set=(e,t,_=localStorage,a=__md_scope)=>{try{_.setItem(a.pathname+"."+e,JSON.stringify(t))}catch(e){}},document.documentElement.setAttribute("data-platform",navigator.platform)</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo">
|
||||
|
||||
|
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
||||
<label class="md-overlay" for="__drawer" aria-label="Navigation"></label>
|
||||
<div data-md-component="skip">
|
||||
|
||||
|
||||
<a href="#markdown-in-5min" class="md-skip">
|
||||
Skip to content
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<header class="md-header md-header--shadow" data-md-component="header">
|
||||
<nav class="md-header__inner md-grid" aria-label="Header">
|
||||
<a href="./.." title="up" class="md-header__button md-logo" aria-label="up" data-md-component="logo">
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-book-open" viewBox="0 0 24 24"><path d="M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>
|
||||
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer" aria-label="Navigation">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-menu" viewBox="0 0 24 24"><path d="M4 5h16M4 12h16M4 19h16"/></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
up
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Markdown in 5min
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="none" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
|
||||
|
||||
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg>
|
||||
</label>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="none" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
|
||||
|
||||
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-moon" viewBox="0 0 24 24"><path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401"/></svg>
|
||||
</label>
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-header__button md-icon" for="__search" aria-label="Search">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-search" viewBox="0 0 24 24"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg>
|
||||
</label>
|
||||
<div class="md-search" data-md-component="search" role="dialog" aria-label="Search">
|
||||
<button type="button" class="md-search__button">
|
||||
Search
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="md-header__source">
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
</header>
|
||||
|
||||
<div class="md-container" data-md-component="container">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a href="./.." title="up" class="md-nav__button md-logo" aria-label="up" data-md-component="logo">
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-book-open" viewBox="0 0 24 24"><path d="M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>
|
||||
|
||||
</a>
|
||||
up
|
||||
</label>
|
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="./.." class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-rocket" viewBox="0 0 24 24"><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09"/><path d="M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z"/><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Welcome!
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__link md-nav__link--active" for="__toc">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M22.27 19.385H1.73A1.73 1.73 0 0 1 0 17.655V6.345a1.73 1.73 0 0 1 1.73-1.73h20.54A1.73 1.73 0 0 1 24 6.345v11.308a1.73 1.73 0 0 1-1.73 1.731zM5.769 15.923v-4.5l2.308 2.885 2.307-2.885v4.5h2.308V8.078h-2.308l-2.307 2.885-2.308-2.885H3.46v7.847zM21.232 12h-2.309V8.077h-2.307V12h-2.308l3.461 4.039z"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Markdown in 5min
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
|
||||
<a href="././" class="md-nav__link md-nav__link--active">
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M22.27 19.385H1.73A1.73 1.73 0 0 1 0 17.655V6.345a1.73 1.73 0 0 1 1.73-1.73h20.54A1.73 1.73 0 0 1 24 6.345v11.308a1.73 1.73 0 0 1-1.73 1.731zM5.769 15.923v-4.5l2.308 2.885 2.307-2.885v4.5h2.308V8.078h-2.308l-2.307 2.885-2.308-2.885H3.46v7.847zM21.232 12h-2.309V8.077h-2.307V12h-2.308l3.461 4.039z"/></svg>
|
||||
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
Markdown in 5min
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary" aria-label="On this page">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
On this page
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#headers" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Headers
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#text-formatting" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Text formatting
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#links-and-images" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Links and images
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#lists" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Lists
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#blockquotes" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Blockquotes
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#code-blocks" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Code blocks
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#tables" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Tables
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#horizontal-rule" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Horizontal rule
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#task-lists" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Task lists
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#escaping-characters" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Escaping characters
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#line-breaks" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Line breaks
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
|
||||
<div class="md-sidebar-button__wrapper">
|
||||
<label class="md-sidebar-button" for="__toc"></label>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary" aria-label="On this page">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
On this page
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#headers" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Headers
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#text-formatting" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Text formatting
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#links-and-images" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Links and images
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#lists" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Lists
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#blockquotes" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Blockquotes
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#code-blocks" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Code blocks
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#tables" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Tables
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#horizontal-rule" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Horizontal rule
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#task-lists" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Task lists
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#escaping-characters" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Escaping characters
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#line-breaks" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
<span class="md-typeset">
|
||||
Line breaks
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-content" data-md-component="content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<article class="md-content__inner md-typeset">
|
||||
|
||||
|
||||
|
||||
<h1 id="markdown-in-5min">Markdown in 5min<a class="headerlink" href="#markdown-in-5min" title="Permanent link">¶</a></h1>
|
||||
<h2 id="headers">Headers<a class="headerlink" href="#headers" title="Permanent link">¶</a></h2>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a># H1 Header
|
||||
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a>## H2 Header
|
||||
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a>### H3 Header
|
||||
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a>#### H4 Header
|
||||
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a>##### H5 Header
|
||||
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a>###### H6 Header
|
||||
</span></code></pre></div>
|
||||
<h2 id="text-formatting">Text formatting<a class="headerlink" href="#text-formatting" title="Permanent link">¶</a></h2>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a>**bold text**
|
||||
</span><span id="__span-1-2"><a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a>*italic text*
|
||||
</span><span id="__span-1-3"><a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a>***bold and italic***
|
||||
</span><span id="__span-1-4"><a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a>~~strikethrough~~
|
||||
</span><span id="__span-1-5"><a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a>`inline code`
|
||||
</span></code></pre></div>
|
||||
<h2 id="links-and-images">Links and images<a class="headerlink" href="#links-and-images" title="Permanent link">¶</a></h2>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a>[Link text](https://example.com)
|
||||
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a>[Link with title](https://example.com "Hover title")
|
||||
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a>
|
||||
</span><span id="__span-2-4"><a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a>
|
||||
</span></code></pre></div>
|
||||
<h2 id="lists">Lists<a class="headerlink" href="#lists" title="Permanent link">¶</a></h2>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a>Unordered:
|
||||
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a>
|
||||
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a>- Item 1
|
||||
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a>- Item 2
|
||||
</span><span id="__span-3-5"><a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a> - Nested item
|
||||
</span><span id="__span-3-6"><a id="__codelineno-3-6" name="__codelineno-3-6" href="#__codelineno-3-6"></a>
|
||||
</span><span id="__span-3-7"><a id="__codelineno-3-7" name="__codelineno-3-7" href="#__codelineno-3-7"></a>Ordered:
|
||||
</span><span id="__span-3-8"><a id="__codelineno-3-8" name="__codelineno-3-8" href="#__codelineno-3-8"></a>
|
||||
</span><span id="__span-3-9"><a id="__codelineno-3-9" name="__codelineno-3-9" href="#__codelineno-3-9"></a>1. First item
|
||||
</span><span id="__span-3-10"><a id="__codelineno-3-10" name="__codelineno-3-10" href="#__codelineno-3-10"></a>2. Second item
|
||||
</span><span id="__span-3-11"><a id="__codelineno-3-11" name="__codelineno-3-11" href="#__codelineno-3-11"></a>3. Third item
|
||||
</span></code></pre></div>
|
||||
<h2 id="blockquotes">Blockquotes<a class="headerlink" href="#blockquotes" title="Permanent link">¶</a></h2>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a>> This is a blockquote
|
||||
</span><span id="__span-4-2"><a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a>> Multiple lines
|
||||
</span><span id="__span-4-3"><a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a>>> Nested quote
|
||||
</span></code></pre></div>
|
||||
<h2 id="code-blocks">Code blocks<a class="headerlink" href="#code-blocks" title="Permanent link">¶</a></h2>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a>```javascript
|
||||
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a>function hello() {
|
||||
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a> console.log("Hello, world!");
|
||||
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a>}
|
||||
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a>```
|
||||
</span></code></pre></div>
|
||||
<h2 id="tables">Tables<a class="headerlink" href="#tables" title="Permanent link">¶</a></h2>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a>| Header 1 | Header 2 | Header 3 |
|
||||
</span><span id="__span-6-2"><a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a>|----------|----------|----------|
|
||||
</span><span id="__span-6-3"><a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a>| Row 1 | Data | Data |
|
||||
</span><span id="__span-6-4"><a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a>| Row 2 | Data | Data |
|
||||
</span></code></pre></div>
|
||||
<h2 id="horizontal-rule">Horizontal rule<a class="headerlink" href="#horizontal-rule" title="Permanent link">¶</a></h2>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a>---
|
||||
</span><span id="__span-7-2"><a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a>or
|
||||
</span><span id="__span-7-3"><a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a>***
|
||||
</span><span id="__span-7-4"><a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a>or
|
||||
</span><span id="__span-7-5"><a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a>___
|
||||
</span></code></pre></div>
|
||||
<h2 id="task-lists">Task lists<a class="headerlink" href="#task-lists" title="Permanent link">¶</a></h2>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-8-1"><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a>- [x] Completed task
|
||||
</span><span id="__span-8-2"><a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a>- [ ] Incomplete task
|
||||
</span><span id="__span-8-3"><a id="__codelineno-8-3" name="__codelineno-8-3" href="#__codelineno-8-3"></a>- [ ] Another task
|
||||
</span></code></pre></div>
|
||||
<h2 id="escaping-characters">Escaping characters<a class="headerlink" href="#escaping-characters" title="Permanent link">¶</a></h2>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-9-1"><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a>Use backslash to escape: \* \_ \# \`
|
||||
</span></code></pre></div>
|
||||
<h2 id="line-breaks">Line breaks<a class="headerlink" href="#line-breaks" title="Permanent link">¶</a></h2>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-10-1"><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a>End a line with two spaces
|
||||
</span><span id="__span-10-2"><a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a>to create a line break.
|
||||
</span><span id="__span-10-3"><a id="__codelineno-10-3" name="__codelineno-10-3" href="#__codelineno-10-3"></a>
|
||||
</span><span id="__span-10-4"><a id="__codelineno-10-4" name="__codelineno-10-4" href="#__codelineno-10-4"></a>Or use a blank line for a new paragraph.
|
||||
</span></code></pre></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
</div>
|
||||
|
||||
|
||||
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
|
||||
|
||||
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
|
||||
</div>
|
||||
|
||||
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-circle-arrow-up" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m16 12-4-4-4 4M12 16V8"/></svg>
|
||||
Back to top
|
||||
</button>
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="md-footer">
|
||||
|
||||
|
||||
|
||||
<nav class="md-footer__inner md-grid" aria-label="Footer" >
|
||||
|
||||
|
||||
<a href="./.." class="md-footer__link md-footer__link--prev" aria-label="Previous: Welcome!">
|
||||
<div class="md-footer__button md-icon">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-arrow-left" viewBox="0 0 24 24"><path d="m12 19-7-7 7-7M19 12H5"/></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
<div class="md-ellipsis">
|
||||
Welcome!
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
|
||||
<div class="md-copyright__highlight">
|
||||
Copyright © 2026 The authors
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://zensical.org/" target="_blank" rel="noopener">
|
||||
Zensical
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script id="__config" type="application/json">{"annotate":null,"base":"..","features":["announce.dismiss","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.top","navigation.tracking","search.highlight"],"search":"../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":null}</script>
|
||||
|
||||
|
||||
<script src="../assets/javascripts/bundle.6e5f0216.min.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
25
overrides/main.html
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{#
|
||||
Action Points feature flag.
|
||||
|
||||
Exposes the zensical.toml setting `[project.extra.action_points] enabled`
|
||||
to client-side JS as `window.TOA_ACTION_POINTS_ENABLED`. This block renders
|
||||
in <head>, before extra_javascript loads in {% block scripts %}, so the
|
||||
action-points engine in docs/javascripts/extra.js can bail out immediately
|
||||
when the feature is disabled.
|
||||
|
||||
Set `enabled = false` in zensical.toml to turn the ENTIRE interactive
|
||||
checklist feature off — no localStorage, no nav badges, no confetti, no
|
||||
per-click work. Checkboxes then fall back to Material's default read-only
|
||||
rendering. Defaults to ON when the key is absent.
|
||||
#}
|
||||
{% block extrahead %}
|
||||
{{ super() }}
|
||||
<script>
|
||||
window.TOA_ACTION_POINTS_ENABLED =
|
||||
{{ "false" if config.extra.action_points and config.extra.action_points.enabled == false else "true" }};
|
||||
window.TOA_KEEP_IN_TOUCH_ENDPOINT =
|
||||
{{ ('"' + config.extra.keep_in_touch.endpoint + '"') if config.extra.keep_in_touch and config.extra.keep_in_touch.endpoint else '""' }};
|
||||
</script>
|
||||
{% endblock %}
|
||||
13
overrides/partials/comments.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{% include "partials/keep-in-touch.html" %}
|
||||
|
||||
<h2 id="__comments">{{ lang.t("meta.comments") }}</h2>
|
||||
<div id="cusdis_thread"
|
||||
data-host="{{ config.extra.cusdis.host }}"
|
||||
data-app-id="{{ config.extra.cusdis.app_id }}"
|
||||
data-page-id="{{ page.canonical_url }}"
|
||||
data-page-url="{{ page.canonical_url }}"
|
||||
data-page-title="{{ page.title }}"
|
||||
data-theme="auto">
|
||||
</div>
|
||||
<script async defer src="{{ config.extra.cusdis.host }}/js/cusdis.es.js"></script>
|
||||
<noscript>Please enable JavaScript to view the comments.</noscript>
|
||||
20
overrides/partials/copyright.html
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<div class="md-copyright">
|
||||
{% if config.copyright %}
|
||||
<div class="md-copyright__highlight">
|
||||
{{ config.copyright }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not config.extra.generator == false %}
|
||||
<div class="md-copyright__badges">
|
||||
<span class="md-copyright__zensical">
|
||||
Built with
|
||||
<a href="https://zensical.org/" target="_blank" rel="noopener">
|
||||
Zensical
|
||||
</a>
|
||||
</span>
|
||||
<a href="https://grebedoc.dev" class="md-copyright__grebedoc" title="served by Grebedoc">
|
||||
<img src="https://grebedoc.dev/88x31.gif" alt="served by Grebedoc" style="image-rendering: pixelated; height: 31px; width: 88px;">
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
92
overrides/partials/keep-in-touch.html
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
{#
|
||||
Keep In Touch — newsletter / contact capture admonition.
|
||||
|
||||
Rendered above the comments section on every page (included from
|
||||
partials/comments.html). Lets a visitor leave a WhatsApp number and/or
|
||||
email to get updates. Each field submits independently; once both are
|
||||
present the widget asks for their name. Submissions POST as JSON to the
|
||||
endpoint configured in zensical.toml under [project.extra.keep_in_touch].
|
||||
|
||||
Config (zensical.toml):
|
||||
[project.extra.keep_in_touch]
|
||||
endpoint = "https://subscribe.krystl.org/api/subscribe"
|
||||
enabled = true
|
||||
|
||||
The endpoint is also exposed to JS as window.TOA_KEEP_IN_TOUCH_ENDPOINT
|
||||
via overrides/main.html. Styling lives in docs/stylesheets/extra.css
|
||||
(.toa-kit-*), behaviour in docs/javascripts/extra.js (Keep-In-Touch IIFE).
|
||||
#}
|
||||
{% if config.extra.keep_in_touch and config.extra.keep_in_touch.enabled != false %}
|
||||
<section class="toa-kit gp-reveal"
|
||||
data-endpoint="{{ config.extra.keep_in_touch.endpoint | default('') }}"
|
||||
aria-labelledby="toa-kit-title">
|
||||
<div class="toa-kit__inner">
|
||||
<div class="toa-kit__glow" aria-hidden="true"></div>
|
||||
|
||||
<header class="toa-kit__header">
|
||||
<span class="toa-kit__icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor"
|
||||
stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
viewBox="0 0 24 24" class="lucide">
|
||||
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
|
||||
<path d="m22 6-10 7L2 6"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<div class="toa-kit__heading">
|
||||
<h2 id="toa-kit-title" class="toa-kit__titletext">Keep In Touch</h2>
|
||||
<p class="toa-kit__sub">Leave your WhatsApp or email to get updates on the journey.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<form class="toa-kit__form" novalidate>
|
||||
{# WhatsApp #}
|
||||
<label class="toa-kit__field" data-kind="whatsapp">
|
||||
<span class="toa-kit__fieldicon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor"
|
||||
stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
viewBox="0 0 24 24" class="lucide">
|
||||
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<input type="tel" class="toa-kit__input" name="whatsapp"
|
||||
inputmode="tel" autocomplete="tel"
|
||||
placeholder="WhatsApp number" aria-label="WhatsApp number">
|
||||
</label>
|
||||
|
||||
{# Email #}
|
||||
<label class="toa-kit__field" data-kind="email">
|
||||
<span class="toa-kit__fieldicon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor"
|
||||
stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
viewBox="0 0 24 24" class="lucide">
|
||||
<rect width="20" height="16" x="2" y="4" rx="2"></rect>
|
||||
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<input type="email" class="toa-kit__input" name="email"
|
||||
inputmode="email" autocomplete="email"
|
||||
placeholder="Email address" aria-label="Email address">
|
||||
</label>
|
||||
|
||||
{# Name — revealed after both whatsapp + email are captured #}
|
||||
<label class="toa-kit__field toa-kit__field--name" data-kind="name" hidden>
|
||||
<span class="toa-kit__fieldicon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor"
|
||||
stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
viewBox="0 0 24 24" class="lucide">
|
||||
<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="12" cy="7" r="4"></circle>
|
||||
</svg>
|
||||
</span>
|
||||
<input type="text" class="toa-kit__input" name="name"
|
||||
autocomplete="name"
|
||||
placeholder="Your name (optional)" aria-label="Your name">
|
||||
</label>
|
||||
|
||||
<button type="submit" class="toa-kit__send">Send</button>
|
||||
</form>
|
||||
|
||||
<p class="toa-kit__notice" role="status" aria-live="polite" hidden></p>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
296
planning/action-points-prd.md
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
# Action Points — Interactive Checklist PRD
|
||||
|
||||
**Status:** Draft
|
||||
**Author:** aja + Hermes
|
||||
**Date:** 2026-06-03
|
||||
|
||||
---
|
||||
|
||||
## 1. Problem Statement
|
||||
|
||||
The Tree of Ascension site contains practices and strategies that invite the reader to *do* something — meditate, journal, take a walk barefoot, migrate off a service. Right now those calls to action are flat text. A reader who returns tomorrow has no way to see what they've already tried or what remains.
|
||||
|
||||
We want to make the site *participatory*: let readers check off action items, see their progress, and feel a sense of momentum. Completion should be visible and celebratory — not gamified in a manipulative way, but genuinely satisfying.
|
||||
|
||||
---
|
||||
|
||||
## 2. Feature Overview
|
||||
|
||||
| # | Feature | Summary |
|
||||
|---|---------|---------|
|
||||
| 1 | **Checkable action points** | Markdown `- [ ]` task lists that are clickable and persist checked state in `localStorage` |
|
||||
| 2 | **Heading counters** | Each heading with action items underneath shows a counter (e.g., `3/5`). When all items are checked, the heading changes color and confetti drops from the top of the page |
|
||||
| 3 | **Navigation badges** | Sidebar navigation items show a checkmark and color change when all action items on that page are checked |
|
||||
| 4 | **Page-level completion** | The top-of-page heading (h1) reflects overall page completion with a counter |
|
||||
|
||||
---
|
||||
|
||||
## 3. Detailed Specifications
|
||||
|
||||
### 3.1 Checkable Action Points
|
||||
|
||||
**What they are:**
|
||||
Any `- [ ]` Markdown task list item rendered on a page. The site already uses `pymdownx.tasklist` with `custom_checkbox = true`, which renders checkboxes. We layer interactivity + persistence on top.
|
||||
|
||||
**Behavior:**
|
||||
- Clicking a checkbox toggles its state (unchecked ↔ checked)
|
||||
- State is immediately persisted to `localStorage`
|
||||
- On page load (and on instant navigation), previously saved state is restored
|
||||
- If a checkbox's label text no longer matches any saved entry (content was edited), the stale entry is silently ignored
|
||||
|
||||
**Checkbox identification:**
|
||||
Each checkbox is identified by a key derived from:
|
||||
1. The page's canonical URL path (e.g., `/practices/daily-sadhana/`)
|
||||
2. The normalized label text (trimmed, lowercased, collapsed whitespace)
|
||||
|
||||
```
|
||||
Key = URL + "::" + normalized_label
|
||||
```
|
||||
|
||||
This is stable across reloads and survives minor whitespace changes but intentionally breaks on substantial rewrites (which should reset progress anyway).
|
||||
|
||||
**Visual style:**
|
||||
- Unchecked: current Zensical tasklist styling (green-tinted)
|
||||
- Checked: strikethrough + muted color, consistent with existing site palette
|
||||
|
||||
---
|
||||
|
||||
### 3.2 Heading Counters & Completion Celebration
|
||||
|
||||
**Counter display:**
|
||||
For each heading (h2, h3, h4) that has one or more action items in its scope, a pill badge is floated to the right of the heading:
|
||||
```
|
||||
## Meditation [0/2]
|
||||
```
|
||||
When partially complete:
|
||||
```
|
||||
## Meditation [1/2]
|
||||
```
|
||||
When fully complete — the heading and badge both shift to the site's accent aurora purple (`--gp-accent`).
|
||||
|
||||
**Heading scope:**
|
||||
An action item belongs to the nearest preceding heading at or above its level. Concretely:
|
||||
- Items after an h2 but before the next h2 belong to that h2
|
||||
- Items after an h3 but before the next h2 or h3 belong to that h3
|
||||
|
||||
**Confetti trigger:**
|
||||
When the last unchecked item under a heading is checked (counter goes from `(n-1)/n` to `n/n`):
|
||||
- A confetti burst animates from the top of the viewport
|
||||
- Confetti uses the site's palette (greens, aurora purple, soft gold)
|
||||
- Animation lasts ~3 seconds
|
||||
- Respects `prefers-reduced-motion` (skips entirely)
|
||||
|
||||
**Confetti implementation:** Custom canvas animation (zero dependency).
|
||||
Two tiers:
|
||||
- **Heading completion:** Subtle aurora particle shower — ~2s, calm, particles in site palette. Accompanied by a soft 432 Hz sine chime (Web Audio API, gentle attack/decay envelope).
|
||||
- **Page-level completion:** More energetic burst — ~3s, denser particles. Accompanied by an ascending arpeggio centered on 528 Hz (Web Audio API, sine waves with smooth envelope).
|
||||
|
||||
Both respect `prefers-reduced-motion` (confetti skipped, sounds skipped).
|
||||
|
||||
---
|
||||
|
||||
### 3.3 Navigation Integration
|
||||
|
||||
**Sidebar nav items:**
|
||||
Each link in the left sidebar that points to a page with action items:
|
||||
- Displays a pill badge next to the link text showing the completion count (e.g., `2/5`)
|
||||
- When all items on that page are complete, the badge becomes a ✓ checkmark and the link text shifts to the accent color
|
||||
|
||||
**Index page aggregation:**
|
||||
Section index pages (e.g., `/practices/`) aggregate completion across all their sub-pages. The badge shows the combined total — e.g., `12/28` summing all practice pages. Sub-page grouping is derived from URL structure: `/practices/daily-sadhana/` is a child of `/practices/`.
|
||||
|
||||
**How it works:**
|
||||
1. After a page renders and checkboxes are initialized, compute `{ checked, total }` for that page
|
||||
2. Store the summary in `localStorage` under the page URL
|
||||
3. Find the corresponding `<a>` element in the sidebar navigation and inject the badge/checkmark
|
||||
4. Re-run on every page navigation (instant or full)
|
||||
|
||||
**Edge cases:**
|
||||
- Pages with no action items: no badge, no color change
|
||||
- Deleted pages: stale localStorage entries don't render (no nav element to match)
|
||||
|
||||
---
|
||||
### 3.4 Page-Level Heading
|
||||
|
||||
The top-of-page `<h1>` gets a pill badge (right-aligned) showing overall page progress:
|
||||
```
|
||||
# Daily Sadhana [4/12]
|
||||
```
|
||||
Same color-change logic as section headings: when complete, the h1 turns accent-colored.
|
||||
|
||||
The h1 counter aggregates *all* action items on the page — it's the sum of all section counts.
|
||||
|
||||
---
|
||||
|
||||
### 3.5 Progress Export (trivial add-on)
|
||||
|
||||
A small "Download my progress" link in the page footer or near the comments section. Clicking it triggers a browser download of a JSON file containing the full localStorage state. This lets users:
|
||||
- Back up their progress before clearing browser data
|
||||
- Share their completion state (import could come later)
|
||||
|
||||
Implementation is ~10 lines: read `localStorage`, create a `Blob`, trigger download via a temporary `<a>` element.
|
||||
|
||||
---
|
||||
|
||||
## 4. Technical Design
|
||||
|
||||
### 4.1 localStorage Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"toa-action-points": {
|
||||
"version": 1,
|
||||
"pages": {
|
||||
"/practices/daily-sadhana/": {
|
||||
"lastUpdated": "2026-06-03T12:00:00.000Z",
|
||||
"checked": [
|
||||
"sit. breathe. that's the whole instruction.",
|
||||
"write down three things you are genuinely grateful for"
|
||||
]
|
||||
},
|
||||
"/strategies/digital-sovereignty/": {
|
||||
"lastUpdated": "2026-06-03T12:30:00.000Z",
|
||||
"checked": [
|
||||
"switch from wifi to ethernet for your main computer"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Keys are the site-relative URL path (without domain; works across environments)
|
||||
- `checked` is an array of normalized label strings
|
||||
- `version` allows future schema migrations
|
||||
- One key per page keeps reads/writes small
|
||||
|
||||
### 4.2 Instant Navigation Compatibility
|
||||
|
||||
The site uses `navigation.instant` (SPA-style page transitions). Zensical/Material for MkDocs exposes `document$` as an observable for navigation events.
|
||||
|
||||
Our JS hooks into:
|
||||
- `DOMContentLoaded` — for initial page load
|
||||
- `document$.subscribe` — for instant navigation transitions
|
||||
|
||||
On each navigation:
|
||||
1. Wait for DOM to settle (the new page content is rendered)
|
||||
2. Scan for tasklist items
|
||||
3. Restore saved state from localStorage
|
||||
4. Inject counters into headings and h1
|
||||
5. Update sidebar nav badges for *all* pages (not just current — because the current page's completion may have changed)
|
||||
|
||||
### 4.3 Storage Limit
|
||||
|
||||
`localStorage` is typically 5–10 MB per origin. Our schema is compact (a few KB even with many pages). No practical risk of hitting the limit.
|
||||
|
||||
### 4.4 Performance
|
||||
|
||||
- DOM scanning on each navigation: O(n) where n = number of tasklist items on a page (typically < 30)
|
||||
- Nav badge updates: O(sidebar links × pages with data), well under 1ms
|
||||
- confetti: canvas-based, runs off main thread via `requestAnimationFrame`
|
||||
|
||||
All work is < 5ms per navigation; no perceptible impact.
|
||||
|
||||
---
|
||||
|
||||
## 5. Future: Cross-Device Persistence (v2)
|
||||
|
||||
### 5.1 Problem
|
||||
`localStorage` is per-browser, per-device. A reader who checks items on their phone won't see them on their laptop.
|
||||
|
||||
### 5.2 Solution sketch
|
||||
- User optionally enters their email address
|
||||
- We store a mapping: `email → checked_items` on a lightweight server
|
||||
- On page load, if an email is stored in localStorage, fetch state from the server
|
||||
- On checkbox toggle, sync to server (debounced)
|
||||
- No authentication required — email is the identifier (like Cusdis comments)
|
||||
- Server can be a simple SQLite-backed Python/FastAPI service or even a Cloudflare Worker + D1
|
||||
|
||||
### 5.3 Why not now
|
||||
- Requires deploying and maintaining a server
|
||||
- Adds latency and failure modes
|
||||
- `localStorage` solves 80% of the value with 0% of the infrastructure cost
|
||||
- We ship v1, learn from usage, then decide if cross-device is worth it
|
||||
|
||||
---
|
||||
|
||||
## 6. Content Authoring Guide
|
||||
|
||||
For content authors, "action points" are simply `- [ ]` Markdown task lists. No special syntax, no frontmatter, no directives.
|
||||
|
||||
```markdown
|
||||
## Meditation
|
||||
|
||||
- [ ] Sit quietly for 5 minutes
|
||||
- [ ] Notice when the mind wanders and return to breath
|
||||
- [ ] Do this every morning for one week
|
||||
```
|
||||
|
||||
The JS layer automatically detects these and adds interactivity. To opt a page *out* of action-point tracking entirely (e.g., index pages with task lists that aren't meant to be checked off), add frontmatter:
|
||||
|
||||
```yaml
|
||||
---
|
||||
action_points: false
|
||||
---
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Open Questions
|
||||
|
||||
1. **Confetti style — subtle or playful?**
|
||||
A gentle aurora-colored particle shower that respects the site's calm aesthetic, or a more energetic celebration? The site's ethos ("not gamified in a manipulative way, but genuinely satisfying") points toward subtle — soft particles in the site palette, ~2-second duration, no sound.
|
||||
|
||||
2. **Should index pages (e.g., `/practices/`) track action items?**
|
||||
Index pages use grid cards, not task lists. Likely `action_points: false` by default for any page without `- [ ]` items. But if someone adds checklist items to an index, should they track? Probably yes — detection is automatic unless explicitly opted out.
|
||||
|
||||
3. **Counter placement on headings — inline badge or superscript?**
|
||||
`## Meditation [0/2]` (inline, after heading text) vs `## Meditation` with a small pill badge. Inline is simpler, less DOM manipulation, and works with existing heading anchors. I'd recommend inline.
|
||||
|
||||
4. **Navigation badges — all pages or only pages with action items?**
|
||||
Only pages with at least one action item should get a badge. Empty counters clutter the sidebar. This means we compute on first page visit and store the `total` count — pages with total=0 get no badge.
|
||||
|
||||
5. **When a user edits the Markdown source (adding/removing items), how should we handle stale localStorage entries?**
|
||||
Stale entries (label text no longer matches any rendered checkbox) are silently dropped. New items start unchecked. This is the least-surprising behavior — edits "reset" progress only for changed items, not the whole page.
|
||||
|
||||
6. **Should completion state be exportable/downloadable?**
|
||||
A "download my progress" button would let users save their state as a JSON file before clearing browser data. Nice-to-have for v1.1.
|
||||
|
||||
7. **Confetti: custom canvas or `canvas-confetti` library?**
|
||||
- Custom: ~60 lines of JS, full control over palette and behavior, zero dependency, but more code to maintain
|
||||
- `canvas-confetti`: battle-tested, good defaults, one function call, but adds ~7 KB dependency
|
||||
|
||||
Leaning custom — the palette matching and reduced-motion respect are trivial to implement and the site already values self-contained minimalism.
|
||||
|
||||
---
|
||||
|
||||
## 8. Implementation Plan (high-level)
|
||||
|
||||
| Phase | What | Files touched |
|
||||
|-------|------|--------------|
|
||||
| 1 | Core checkbox persistence (read/write localStorage) | `docs/javascripts/extra.js` |
|
||||
| 2 | Heading counters + color change | `docs/javascripts/extra.js`, `docs/stylesheets/extra.css` |
|
||||
| 3 | Confetti on completion | `docs/javascripts/extra.js` (custom canvas) |
|
||||
| 4 | Navigation badge injection | `docs/javascripts/extra.js`, `docs/stylesheets/extra.css` |
|
||||
| 5 | Page-level h1 counter | `docs/javascripts/extra.js`, `docs/stylesheets/extra.css` |
|
||||
| 6 | Opt-out frontmatter support | `docs/javascripts/extra.js` |
|
||||
| 7 | Test across all content pages + mobile | manual QA |
|
||||
|
||||
All JS goes in the existing `docs/javascripts/extra.js`. All CSS in `docs/stylesheets/extra.css`. No new files, no new dependencies, no build pipeline changes.
|
||||
|
||||
---
|
||||
|
||||
## 9. Success Criteria
|
||||
|
||||
- [ ] Clicking a `- [ ]` checkbox toggles its visual state
|
||||
- [ ] Refreshing the page preserves checked state
|
||||
- [ ] Navigating to another page and back preserves checked state
|
||||
- [ ] Headings show accurate counters (e.g., `2/5`)
|
||||
- [ ] When a heading reaches full completion, it changes to accent color
|
||||
- [ ] Confetti plays when the last item under a heading is checked (and not on reduced-motion)
|
||||
- [ ] Navigation sidebar shows badges for pages with action items
|
||||
- [ ] Fully-completed pages show ✓ checkmark in nav
|
||||
- [ ] Page h1 shows overall completion counter
|
||||
- [ ] Zero console errors on any page
|
||||
- [ ] Works on mobile (touch events fire correctly on checkboxes)
|
||||
- [ ] No visual regression on pages without action items
|
||||
1039
practices/index.html
17
pyproject.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "up"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = []
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["_extensions"]
|
||||
|
||||
[dependency-groups]
|
||||
dev = ["zensical>=0.0.43"]
|
||||
42
sitemap.xml
|
|
@ -1,42 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://tree.ad/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/practices/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/practices/daily-sadhana/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/practices/digital-wellness/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/practices/grounding-in-nature/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/practices/nourishing-the-body/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/practices/spiritual-hygiene/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/strategies/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/strategies/collective-awakening/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/strategies/community-sovereignty/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/strategies/digital-sovereignty/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/strategies/finding-purpose/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://tree.ad/contributing/</loc>
|
||||
</url>
|
||||
</urlset>
|
||||
4
subscribe-service/.dockerignore
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
node_modules
|
||||
data
|
||||
.git
|
||||
*.md
|
||||
33
subscribe-service/Dockerfile
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# ── Subscribe Service ────────────────────────────────────────────────────
|
||||
# Keep In Touch — subscribe capture endpoint for Tree of Ascension docs.
|
||||
#
|
||||
# Deploy on Coolify:
|
||||
# 1. Point the service to this repo (or a subfolder if supported)
|
||||
# 2. Set Build Pack: Dockerfile
|
||||
# 3. Add a persistent volume at /app/data
|
||||
# 4. Set env vars (PORT, ALLOW_ORIGIN, ADMIN_TOKEN)
|
||||
# 5. Map your domain (e.g. subscribe.krystl.org)
|
||||
|
||||
FROM node:22-alpine
|
||||
|
||||
# Create unprivileged user
|
||||
RUN addgroup -S app && adduser -S -G app app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Dependencies first for layer caching
|
||||
COPY package.json ./
|
||||
RUN npm install --omit=dev && npm cache clean --force
|
||||
|
||||
# Application
|
||||
COPY server.js ./
|
||||
|
||||
# Persistent data volume + ownership
|
||||
RUN mkdir -p /app/data && chown -R app:app /app
|
||||
|
||||
USER app
|
||||
|
||||
EXPOSE 8080
|
||||
ENV PORT=8080
|
||||
|
||||
CMD ["node", "server.js"]
|
||||
16
subscribe-service/package.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "toa-subscribe-service",
|
||||
"version": "1.0.0",
|
||||
"description": "Keep In Touch — subscribe capture endpoint for Tree of Ascension docs. Captures WhatsApp / email / name into SQLite.",
|
||||
"type": "module",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "node server.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^11.8.1"
|
||||
}
|
||||
}
|
||||
248
subscribe-service/server.js
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
/**
|
||||
* Keep In Touch — subscribe capture service.
|
||||
*
|
||||
* A tiny dependency-light HTTP service (Node core http + better-sqlite3) that
|
||||
* receives JSON submissions from the docs site "Keep In Touch" widget and
|
||||
* upserts them into a SQLite database. Designed to run in a single container
|
||||
* on Coolify with a persistent volume, mirroring the Cusdis deployment.
|
||||
*
|
||||
* Endpoints:
|
||||
* POST /api/subscribe capture/upsert a subscriber -> { ok: true }
|
||||
* GET /api/health liveness probe -> { ok: true }
|
||||
* GET /api/subscribers list (requires ADMIN_TOKEN) -> [ ... ]
|
||||
*
|
||||
* A submission is keyed by whatsapp OR email — whichever is present. As the
|
||||
* widget collects more fields across submissions (email after whatsapp, then
|
||||
* name), each POST sends the full known set, and we merge into the existing
|
||||
* row rather than creating duplicates.
|
||||
*
|
||||
* Environment:
|
||||
* PORT listen port (default 8080)
|
||||
* DB_PATH SQLite file path (default ./data/subscribers.db)
|
||||
* ALLOW_ORIGIN CORS allow-origin (default "*"; set to your site origin)
|
||||
* ADMIN_TOKEN if set, required as `Authorization: Bearer <token>` for
|
||||
* GET /api/subscribers
|
||||
*/
|
||||
|
||||
import http from "node:http";
|
||||
import { dirname } from "node:path";
|
||||
import { mkdirSync } from "node:fs";
|
||||
import Database from "better-sqlite3";
|
||||
|
||||
const PORT = parseInt(process.env.PORT || "8080", 10);
|
||||
const DB_PATH = process.env.DB_PATH || "./data/subscribers.db";
|
||||
const ALLOW_ORIGIN = process.env.ALLOW_ORIGIN || "*";
|
||||
const ADMIN_TOKEN = process.env.ADMIN_TOKEN || "";
|
||||
const MAX_BODY = 16 * 1024; // 16 KB cap — these payloads are tiny.
|
||||
|
||||
// ── Database ────────────────────────────────────────────────────────────
|
||||
mkdirSync(dirname(DB_PATH), { recursive: true });
|
||||
const db = new Database(DB_PATH);
|
||||
db.pragma("journal_mode = WAL");
|
||||
db.pragma("busy_timeout = 5000");
|
||||
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS subscribers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
whatsapp TEXT,
|
||||
email TEXT,
|
||||
name TEXT,
|
||||
first_page TEXT,
|
||||
first_url TEXT,
|
||||
user_agent TEXT,
|
||||
ip TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_subscribers_email
|
||||
ON subscribers(email) WHERE email IS NOT NULL AND email <> '';
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_subscribers_whatsapp
|
||||
ON subscribers(whatsapp) WHERE whatsapp IS NOT NULL AND whatsapp <> '';
|
||||
`);
|
||||
|
||||
const findByEmail = db.prepare(
|
||||
"SELECT * FROM subscribers WHERE email = ? LIMIT 1"
|
||||
);
|
||||
const findByWhatsApp = db.prepare(
|
||||
"SELECT * FROM subscribers WHERE whatsapp = ? LIMIT 1"
|
||||
);
|
||||
const insertRow = db.prepare(`
|
||||
INSERT INTO subscribers (whatsapp, email, name, first_page, first_url, user_agent, ip)
|
||||
VALUES (@whatsapp, @email, @name, @first_page, @first_url, @user_agent, @ip)
|
||||
`);
|
||||
const updateRow = db.prepare(`
|
||||
UPDATE subscribers
|
||||
SET whatsapp = COALESCE(NULLIF(@whatsapp, ''), whatsapp),
|
||||
email = COALESCE(NULLIF(@email, ''), email),
|
||||
name = COALESCE(NULLIF(@name, ''), name),
|
||||
updated_at = datetime('now')
|
||||
WHERE id = @id
|
||||
`);
|
||||
const listRows = db.prepare(
|
||||
"SELECT * FROM subscribers ORDER BY updated_at DESC LIMIT 1000"
|
||||
);
|
||||
|
||||
// ── Validation / normalization ──────────────────────────────────────────
|
||||
function normEmail(v) {
|
||||
return typeof v === "string" ? v.trim().toLowerCase() : "";
|
||||
}
|
||||
function normWhatsApp(v) {
|
||||
if (typeof v !== "string") return "";
|
||||
const cleaned = v.trim().replace(/[^\d+]/g, "");
|
||||
const digits = cleaned.replace(/[^\d]/g, "");
|
||||
if (digits.length < 7 || digits.length > 15) return "";
|
||||
return cleaned;
|
||||
}
|
||||
function isValidEmail(v) {
|
||||
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v);
|
||||
}
|
||||
function clean(v, max = 200) {
|
||||
return typeof v === "string" ? v.trim().slice(0, max) : "";
|
||||
}
|
||||
|
||||
// Upsert: find an existing row by email or whatsapp, merge; else insert.
|
||||
const upsert = db.transaction((rec) => {
|
||||
let existing = null;
|
||||
if (rec.email) existing = findByEmail.get(rec.email);
|
||||
if (!existing && rec.whatsapp) existing = findByWhatsApp.get(rec.whatsapp);
|
||||
|
||||
if (existing) {
|
||||
updateRow.run({
|
||||
id: existing.id,
|
||||
whatsapp: rec.whatsapp,
|
||||
email: rec.email,
|
||||
name: rec.name,
|
||||
});
|
||||
return { id: existing.id, created: false };
|
||||
}
|
||||
const info = insertRow.run(rec);
|
||||
return { id: info.lastInsertRowid, created: true };
|
||||
});
|
||||
|
||||
// ── HTTP helpers ──────────────────────────────────────────────────────────
|
||||
function cors(res) {
|
||||
res.setHeader("Access-Control-Allow-Origin", ALLOW_ORIGIN);
|
||||
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
|
||||
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||
res.setHeader("Vary", "Origin");
|
||||
}
|
||||
function json(res, status, obj) {
|
||||
cors(res);
|
||||
res.writeHead(status, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify(obj));
|
||||
}
|
||||
function clientIp(req) {
|
||||
const xff = req.headers["x-forwarded-for"];
|
||||
if (typeof xff === "string" && xff.length) return xff.split(",")[0].trim();
|
||||
return req.socket.remoteAddress || "";
|
||||
}
|
||||
|
||||
function readBody(req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let size = 0;
|
||||
const chunks = [];
|
||||
req.on("data", (c) => {
|
||||
size += c.length;
|
||||
if (size > MAX_BODY) {
|
||||
reject(new Error("payload too large"));
|
||||
req.destroy();
|
||||
return;
|
||||
}
|
||||
chunks.push(c);
|
||||
});
|
||||
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
||||
req.on("error", reject);
|
||||
});
|
||||
}
|
||||
|
||||
// ── Server ─────────────────────────────────────────────────────────────
|
||||
const server = http.createServer(async (req, res) => {
|
||||
const url = new URL(req.url, `http://${req.headers.host}`);
|
||||
|
||||
if (req.method === "OPTIONS") {
|
||||
cors(res);
|
||||
res.writeHead(204);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.method === "GET" && url.pathname === "/api/health") {
|
||||
return json(res, 200, { ok: true });
|
||||
}
|
||||
|
||||
if (req.method === "GET" && url.pathname === "/api/subscribers") {
|
||||
if (ADMIN_TOKEN) {
|
||||
const auth = req.headers["authorization"] || "";
|
||||
if (auth !== `Bearer ${ADMIN_TOKEN}`) {
|
||||
return json(res, 401, { ok: false, error: "unauthorized" });
|
||||
}
|
||||
} else {
|
||||
// No admin token configured — refuse rather than leak data.
|
||||
return json(res, 403, { ok: false, error: "admin token not configured" });
|
||||
}
|
||||
return json(res, 200, { ok: true, subscribers: listRows.all() });
|
||||
}
|
||||
|
||||
if (req.method === "POST" && url.pathname === "/api/subscribe") {
|
||||
let raw;
|
||||
try {
|
||||
raw = await readBody(req);
|
||||
} catch (e) {
|
||||
return json(res, 413, { ok: false, error: "payload too large" });
|
||||
}
|
||||
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(raw || "{}");
|
||||
} catch (e) {
|
||||
return json(res, 400, { ok: false, error: "invalid JSON" });
|
||||
}
|
||||
|
||||
const email = normEmail(data.email);
|
||||
const whatsapp = normWhatsApp(data.whatsapp);
|
||||
|
||||
if (email && !isValidEmail(email)) {
|
||||
return json(res, 422, { ok: false, error: "invalid email" });
|
||||
}
|
||||
if (!email && !whatsapp) {
|
||||
return json(res, 422, {
|
||||
ok: false,
|
||||
error: "provide a valid email or whatsapp number",
|
||||
});
|
||||
}
|
||||
|
||||
const rec = {
|
||||
whatsapp,
|
||||
email,
|
||||
name: clean(data.name, 120),
|
||||
first_page: clean(data.page, 300),
|
||||
first_url: clean(data.url, 500),
|
||||
user_agent: clean(req.headers["user-agent"], 400),
|
||||
ip: clientIp(req),
|
||||
};
|
||||
|
||||
try {
|
||||
const result = upsert(rec);
|
||||
return json(res, 200, { ok: true, id: result.id, created: result.created });
|
||||
} catch (e) {
|
||||
console.error("upsert failed:", e);
|
||||
return json(res, 500, { ok: false, error: "server error" });
|
||||
}
|
||||
}
|
||||
|
||||
json(res, 404, { ok: false, error: "not found" });
|
||||
});
|
||||
|
||||
server.listen(PORT, () => {
|
||||
console.log(`[subscribe] listening on :${PORT} (db: ${DB_PATH})`);
|
||||
});
|
||||
|
||||
// Graceful shutdown so SQLite WAL checkpoints cleanly.
|
||||
function shutdown() {
|
||||
server.close(() => {
|
||||
try { db.close(); } catch {}
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
process.on("SIGTERM", shutdown);
|
||||
process.on("SIGINT", shutdown);
|
||||
86
theming.md
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
---
|
||||
title: Theming
|
||||
---
|
||||
|
||||
# Zensical Consciousness Theme — Plan & Prompt Document
|
||||
|
||||
## 1. Goal
|
||||
|
||||
Build a nature/consciousness-themed, beautiful, pastel/iridescent, performance-safe theme
|
||||
for a multi-contributor Zensical awareness site about reigniting the God Spark within.
|
||||
|
||||
## 2. What we learned from Zensical customization
|
||||
|
||||
- Theme extension is mostly additive:
|
||||
- `zensical.toml` → `extra_css` for extra stylesheets.
|
||||
- Page templates can be overridden by placing matching files under `overrides/`.
|
||||
- Site theming is largely controlled by palette/color attributes:
|
||||
- `data-md-color-scheme`
|
||||
- `data-md-color-primary`
|
||||
- `data-md-color-accent`
|
||||
- `extra.css` is the safest layer; it shouldn’t break Zensical if it only adds selectors
|
||||
and doesn’t overwrite core layout-critical rules blindly.
|
||||
- We should keep JS minimal, lazy-friendly, and nonblocking for contributors.
|
||||
|
||||
## 3. Non-goals / constraints
|
||||
|
||||
- No TypeScript/React build pipeline rerouting.
|
||||
- No breaking built-in Zensical navigation/search/skip behavior.
|
||||
- No space/technology motif — instead: botanical/organic/aurora/nature.
|
||||
- Animations must respect load speed and reduced-motion.
|
||||
- Theme should still be readable as Markdown documentation after styling.
|
||||
|
||||
## 4. Adapting MotionSites-style prompts for Kimi
|
||||
|
||||
From the example landing-page prompts:
|
||||
|
||||
- Use: typography system, motion patterns, component thinking, copy composition.
|
||||
- Remove: React/TS/Vite/Framer Motion specifics.
|
||||
- Replace with: plain HTML/CSS + minimal vanilla JS utilities that Zensical can load.
|
||||
|
||||
## 5. Ready-to-run Kimi prompt (refined)
|
||||
|
||||
You are a web designer specializing in calm, premium editorial interfaces.
|
||||
Create a Zensical theme add-on for a consciousness/awakening awareness site.
|
||||
Theme name placeholder: "God Spark". Site title is temporary and may change later.
|
||||
|
||||
Constraints:
|
||||
|
||||
- Output must be plain HTML/CSS/JS only.
|
||||
- Must work as a Zensical `extra.css` drop-in plus optional `overrides/` partials.
|
||||
- Do NOT use React, TypeScript, Tailwind build, Framer Motion, or shadcn/ui.
|
||||
- Do NOT break Zensical core behavior.
|
||||
- Performance-first: no heavy dependencies; any JS should be small and optional.
|
||||
- Accessibility-first: readable contrast, reduced-motion safe, semantic markup.
|
||||
|
||||
Design brief:
|
||||
|
||||
- Aesthetic: futuristic pastel + iridescent, but inspired by nature rather than space/tech.
|
||||
Soft aurora-like gradients, botanical motifs, dappled-light effects, gentle watercolor-like transitions.
|
||||
- Color palette references: soft lavender, mist, pearl, sage, blush, iris, morning frost.
|
||||
- Typography: elegant serif headings, clean sans-serif body. Use standard system fonts or
|
||||
Google Fonts loaded with `preconnect` if needed.
|
||||
- Contributions UI must remain friendly for many contributors: simple class names, clear areas
|
||||
to edit content blocks, great default headings, friendly call-to-action language.
|
||||
|
||||
Functional requirements:
|
||||
|
||||
1. Provide one CSS file intended as Zensical's `extra.css` entry.
|
||||
2. Provide optional HTML/JS micro-animations:
|
||||
- fade-up reveal on scroll via IntersectionObserver
|
||||
- soft parallax cursor glow (optional, turned off by default)
|
||||
3. Provide at least 2 override template examples for `overrides/` (e.g., `main.html`, `footer.html`)
|
||||
that layer glass surfaces and brand text without removing existing placeholders.
|
||||
4. Include README with install steps, customization guidance, and contributor notes.
|
||||
|
||||
## 6. Execution plan
|
||||
|
||||
1. Create an isolated sandbox outside the project.
|
||||
2. Generate theme kit using the prompt above with Kimi.
|
||||
3. Review generated files for Zensical safety before pulling into the project.
|
||||
4. Keep the prompt in `docs/zensical-theme-plan.md` for refinement.
|
||||
|
||||
## 7. Where this is saved
|
||||
|
||||
- Path: `/home/a/w/up/docs/zensical-theme-plan.md`
|
||||
- Reuse by updating this file and rerunning Kimi from the same sandboxed branch/tree.
|
||||
275
uv.lock
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9b/98/518d8e5081007684232226f475082b30087d0f585e8457db087298259f49/click-8.4.1.tar.gz", hash = "sha256:918b5633eddf6b41c32d4f454bf0de810065c74e3f7dbf8ee5452f8be88d3e96", size = 353007, upload-time = "2026-05-22T04:08:37.769Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/0d/67e5b4109ea4a837e80daa87c2c696711955e40449a97e8926672534def2/click-8.4.1-py3-none-any.whl", hash = "sha256:482be17c6991b8c19c5429a1e995d9b0efdbb63172824c41f99965dc0ade8ec2", size = 116639, upload-time = "2026-05-22T04:08:35.26Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deepmerge"
|
||||
version = "2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/3a/b0ba594708f1ad0bc735884b3ad854d3ca3bdc1d741e56e40bbda6263499/deepmerge-2.0.tar.gz", hash = "sha256:5c3d86081fbebd04dd5de03626a0607b809a98fb6ccba5770b62466fe940ff20", size = 19890, upload-time = "2024-08-30T05:31:50.308Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/82/e5d2c1c67d19841e9edc74954c827444ae826978499bde3dfc1d007c8c11/deepmerge-2.0-py3-none-any.whl", hash = "sha256:6de9ce507115cff0bed95ff0ce9ecc31088ef50cbdf09bc90a09349a318b3d00", size = 13475, upload-time = "2024-08-30T05:31:48.659Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2"
|
||||
version = "3.1.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markupsafe" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdown"
|
||||
version = "3.10.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2b/f4/69fa6ed85ae003c2378ffa8f6d2e3234662abd02c10d216c0ba96081a238/markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950", size = 368805, upload-time = "2026-02-09T14:57:26.942Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36", size = 108180, upload-time = "2026-02-09T14:57:25.787Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "3.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.20.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pymdown-extensions"
|
||||
version = "10.21.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markdown" },
|
||||
{ name = "pyyaml" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9e/26/d1015444da4d952a1ca487a236b522eb979766f0295a0bd0c5fc089989a9/pymdown_extensions-10.21.3.tar.gz", hash = "sha256:72cfcf55f07aea0d4af2c4f11dd4e52466ddfb1bb819673146398e0bd3a77354", size = 854140, upload-time = "2026-05-13T12:57:32.267Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/85/545a951eecc270fcd688288c600017e2050a1aacb56c711d208586d3e470/pymdown_extensions-10.21.3-py3-none-any.whl", hash = "sha256:d7a5d08014fc571e80ca21dd6f854e31f94c489800350564d55d15b3c41e76b6", size = 269002, upload-time = "2026-05-13T12:57:30.296Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "up"
|
||||
version = "0.1.0"
|
||||
source = { editable = "." }
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "zensical" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [{ name = "zensical", specifier = ">=0.0.43" }]
|
||||
|
||||
[[package]]
|
||||
name = "zensical"
|
||||
version = "0.0.43"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "deepmerge" },
|
||||
{ name = "jinja2" },
|
||||
{ name = "markdown" },
|
||||
{ name = "pygments" },
|
||||
{ name = "pymdown-extensions" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "tomli" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d4/85/ec45162e7824a8f879d887ef0774ee65926bf7d1064e2eebccc7eaee3378/zensical-0.0.43.tar.gz", hash = "sha256:dc2d3804ff562795c1024130e0c3ce79736467930729dda314f096d0e35b98c8", size = 3932396, upload-time = "2026-05-19T09:44:07.418Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/55/c2/55e0709607ae41c266987c3b91a1a9702b37fbbef0d07eddfe5e25c2d823/zensical-0.0.43-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:17c335362b6bac3a50178181694a964f6d9f0c516fc532129ba5a0a5c4103fb6", size = 12706531, upload-time = "2026-05-19T09:43:32.729Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/64/ce8627bc5ea30556162b29b041fe97d6a6aef2a87b51f12def628e4fa608/zensical-0.0.43-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:b8fe97f185194215f6193af45a17d2b30ebd72c8113e3650f2d7d6767b9c2206", size = 12563012, upload-time = "2026-05-19T09:43:35.962Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/d1/533bc9454f0e06b3d9d8bd2e7ac405308c3d4dee6572acab98f0ed6d1c07/zensical-0.0.43-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c4c85978c765b3e7f347e8102dfe1373d4bbe4229d7008b6bdbf352f1fbcd7f", size = 12947599, upload-time = "2026-05-19T09:43:38.754Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/a0/94f47d6fb592997be7ab9526938c929f0199adf2637c3c2b2b9b2101b28e/zensical-0.0.43-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:90d7c06ffd07b2bdf78bef041d541baba8a3ea51fd2dd84dbdbc5b0229076524", size = 12904911, upload-time = "2026-05-19T09:43:42.434Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/fb/1db3ad9a86ff772f74a8bc60ad5b447aa02a158e70f94adacf50bdd5c40f/zensical-0.0.43-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:60022f4a6b95e46ec0023f51052fcd491743b3ebd08c0066b22a5cf1e741fecd", size = 13269386, upload-time = "2026-05-19T09:43:45.387Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/ee/b24fd0f94885519d851c35615b086d069a1077b0198021a56755395a4633/zensical-0.0.43-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e278eb948a0b7545d50609d713c7c27e366dade4523ff73a311a5d5f136518a", size = 12999364, upload-time = "2026-05-19T09:43:48.549Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/78/401ccd7afd9d2690f81b5319b7f1eed05108154ce20e4207053914518c1c/zensical-0.0.43-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b85e5ab99fbda13823e67c43a4be6e5ebda6600602969c6575e143f20ac203fd", size = 13124392, upload-time = "2026-05-19T09:43:50.965Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/b3/9af6eba5826b0ef143fc8308bd1e219e221441e307a958e39f824ba9ab53/zensical-0.0.43-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:751385accc92cccfd4560dabed7c423870686ef6ede244a67e5c96286af25e8f", size = 13177538, upload-time = "2026-05-19T09:43:53.964Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/6b/cd090bd6659d32692487206469988ee84d41aa6de4cdf9e380f847da90e2/zensical-0.0.43-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:dd3ff5bfa6e65cf3d2550dc639c3da2a3bfa11087b83d57e06623c4c1607d583", size = 13327086, upload-time = "2026-05-19T09:43:56.8Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/5b/ac2555354b5a53cb9c2c942811905c47be0b9f5603d3c1328ee8564333eb/zensical-0.0.43-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:85055a115b12f49c6ab194dcf04f966fc06b690ed6a8ddddd819929fc5f340e6", size = 13284645, upload-time = "2026-05-19T09:43:59.329Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/c6/1688ec6e5be15e3ab367d7804753291bfbdff3109b06e20c19ce30a7129c/zensical-0.0.43-cp310-abi3-win32.whl", hash = "sha256:8a75ddd4bb3cd3c4a8e71d2ebae44c5611fd636c1d355c6124dd96e2f9c52838", size = 12256740, upload-time = "2026-05-19T09:44:02.102Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/a8/d967e70eac810a7e9eb8c5150d6d02848a1f42260f42977c71debed3cb02/zensical-0.0.43-cp310-abi3-win_amd64.whl", hash = "sha256:03a9d1744a6394ad66c355d6f1de04cfd92efa525b0b94bf6dbf6971c5cd2c6b", size = 12496166, upload-time = "2026-05-19T09:44:04.915Z" },
|
||||
]
|
||||
400
zensical.toml
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
# ============================================================================
|
||||
#
|
||||
# The configuration produced by default is meant to highlight the features
|
||||
# that Zensical provides and to serve as a starting point for your own
|
||||
# projects.
|
||||
#
|
||||
# ============================================================================
|
||||
|
||||
[project]
|
||||
|
||||
|
||||
# repo_url = "https://bali.krystl.org/aja/up"
|
||||
# repo_name = "Contribute"
|
||||
# The site_name is shown in the page header and the browser window title
|
||||
#
|
||||
# Read more: https://zensical.org/docs/setup/basics/#site_name
|
||||
site_name = "Tree of Ascension Docs"
|
||||
|
||||
# The site_description is included in the HTML head and should contain a
|
||||
# meaningful description of the site content for use by search engines.
|
||||
#
|
||||
# Read more: https://zensical.org/docs/setup/basics/#site_description
|
||||
site_description = "A living guide for awakening consciousness — practices, teachings, and community for the journey upward"
|
||||
|
||||
# The site_author attribute. This is used in the HTML head element.
|
||||
#
|
||||
# Read more: https://zensical.org/docs/setup/basics/#site_author
|
||||
site_author = "aja"
|
||||
|
||||
# The site_url is the canonical URL for your site. When building online
|
||||
# documentation you should set this.
|
||||
# Read more: https://zensical.org/docs/setup/basics/#site_url
|
||||
site_url = "https://tree.ad/"
|
||||
|
||||
# The copyright notice appears in the page footer and can contain an HTML
|
||||
# fragment.
|
||||
#
|
||||
# Read more: https://zensical.org/docs/setup/basics/#copyright
|
||||
copyright = """
|
||||
Copyright © 2026 The authors
|
||||
"""
|
||||
|
||||
# Zensical supports both implicit navigation and explicitly defined navigation.
|
||||
# If you decide not to define a navigation here then Zensical will simply
|
||||
# derive the navigation structure from the directory structure of your
|
||||
# "docs_dir". The definition below demonstrates how a navigation structure
|
||||
# can be defined using TOML syntax.
|
||||
#
|
||||
# Read more: https://zensical.org/docs/setup/navigation/
|
||||
nav = [
|
||||
{ "Home" = "index.md" },
|
||||
{ "Practices" = [
|
||||
"practices/index.md",
|
||||
"practices/daily-sadhana.md",
|
||||
"practices/digital-wellness.md",
|
||||
"practices/grounding-in-nature.md",
|
||||
"practices/nourishing-the-body.md",
|
||||
"practices/spiritual-hygiene.md",
|
||||
] },
|
||||
{ "Strategies" = [
|
||||
"strategies/index.md",
|
||||
"strategies/collective-awakening.md",
|
||||
"strategies/community-sovereignty.md",
|
||||
"strategies/digital-sovereignty.md",
|
||||
"strategies/finding-purpose.md",
|
||||
] },
|
||||
{ "Contributing" = "contributing/index.md" },
|
||||
]
|
||||
|
||||
# With the "extra_css" option you can add your own CSS styling to customize
|
||||
# your Zensical project according to your needs. You can add any number of
|
||||
# CSS files.
|
||||
#
|
||||
# The path provided should be relative to the "docs_dir".
|
||||
#
|
||||
# Read more: https://zensical.org/docs/customization/#additional-css
|
||||
#
|
||||
extra_css = ["stylesheets/extra.css"]
|
||||
|
||||
# With the `extra_javascript` option you can add your own JavaScript to your
|
||||
# project to customize the behavior according to your needs.
|
||||
#
|
||||
# The path provided should be relative to the "docs_dir".
|
||||
#
|
||||
# Read more: https://zensical.org/docs/customization/#additional-javascript
|
||||
extra_javascript = ["javascripts/extra.js"]
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Section for configuring theme options
|
||||
# ----------------------------------------------------------------------------
|
||||
[project.theme]
|
||||
|
||||
# change this to "classic" to use the traditional Material for MkDocs look.
|
||||
#variant = "classic"
|
||||
|
||||
# Zensical allows you to override specific blocks, partials, or whole
|
||||
# templates as well as to define your own templates. To do this, uncomment
|
||||
# the custom_dir setting below and set it to a directory in which you
|
||||
# keep your template overrides.
|
||||
#
|
||||
# Read more:
|
||||
# - https://zensical.org/docs/customization/#extending-the-theme
|
||||
#
|
||||
custom_dir = "overrides"
|
||||
|
||||
# With the "favicon" option you can set your own image to use as the icon
|
||||
# browsers will use in the browser title bar or tab bar. The path provided
|
||||
# must be relative to the "docs_dir".
|
||||
#
|
||||
# Read more:
|
||||
# - https://zensical.org/docs/setup/logo-and-icons/#favicon
|
||||
# - https://developer.mozilla.org/en-US/docs/Glossary/Favicon
|
||||
#
|
||||
#favicon = "images/favicon.png"
|
||||
|
||||
# Zensical supports more than 60 different languages. This means that the
|
||||
# labels and tooltips that Zensical's templates produce are translated.
|
||||
# The "language" option allows you to set the language used. This language
|
||||
# is also indicated in the HTML head element to help with accessibility
|
||||
# and guide search engines and translation tools.
|
||||
#
|
||||
# The default language is "en" (English). It is possible to create
|
||||
# sites with multiple languages and configure a language selector. See
|
||||
# the documentation for details.
|
||||
#
|
||||
# Read more:
|
||||
# - https://zensical.org/docs/setup/language/
|
||||
#
|
||||
language = "en"
|
||||
|
||||
# Zensical provides a number of feature toggles that change the behavior
|
||||
# of the documentation site.
|
||||
features = [
|
||||
# Zensical includes an announcement bar. This feature allows users to
|
||||
# dismiss it when they have read the announcement.
|
||||
# https://zensical.org/docs/setup/header/#announcement-bar
|
||||
"announce.dismiss",
|
||||
|
||||
# If yeu have a repository configured and turn on this feature, Zensical
|
||||
# will generate an edit button for the page. This works for common
|
||||
# repository hosting services.
|
||||
# https://zensical.org/docs/setup/repository/#content-actions
|
||||
"content.action.edit",
|
||||
|
||||
# If you have a repository configured and turn on this feature, Zensical
|
||||
# will generate a button that allows the user to view the Markdown
|
||||
# code for the current page.
|
||||
# https://zensical.org/docs/setup/repository/#content-actions
|
||||
"content.action.view",
|
||||
|
||||
# Code annotations allow you to add an icon with a tooltip to your
|
||||
# code blocks to provide explanations at crucial points.
|
||||
# https://zensical.org/docs/authoring/code-blocks/#code-annotations
|
||||
"content.code.annotate",
|
||||
|
||||
# This feature turns on a button in code blocks that allow users to
|
||||
# copy the content to their clipboard without first selecting it.
|
||||
# https://zensical.org/docs/authoring/code-blocks/#code-copy-button
|
||||
"content.code.copy",
|
||||
|
||||
# Code blocks can include a button to allow for the selection of line
|
||||
# ranges by the user.
|
||||
# https://zensical.org/docs/authoring/code-blocks/#code-selection-button
|
||||
"content.code.select",
|
||||
|
||||
# Zensical can render footnotes as inline tooltips, so the user can read
|
||||
# the footnote without leaving the context of the document.
|
||||
# https://zensical.org/docs/authoring/footnotes/#footnote-tooltips
|
||||
"content.footnote.tooltips",
|
||||
|
||||
# If you have many content tabs that have the same titles (e.g., "Python",
|
||||
# "JavaScript", "Cobol"), this feature causes all of them to switch to
|
||||
# at the same time when the user chooses their language in one.
|
||||
# https://zensical.org/docs/authoring/content-tabs/#linked-content-tabs
|
||||
"content.tabs.link",
|
||||
|
||||
# With this feature enabled users can add tooltips to links that will be
|
||||
# displayed when the mouse pointer hovers the link.
|
||||
# https://zensical.org/docs/authoring/tooltips/#improved-tooltips
|
||||
"content.tooltips",
|
||||
|
||||
# With this feature enabled, Zensical will automatically hide parts
|
||||
# of the header when the user scrolls past a certain point.
|
||||
# https://zensical.org/docs/setup/header/#automatic-hiding
|
||||
# "header.autohide",
|
||||
|
||||
# Turn on this feature to expand all collapsible sections in the
|
||||
# navigation sidebar by default.
|
||||
# https://zensical.org/docs/setup/navigation/#navigation-expansion
|
||||
# "navigation.expand",
|
||||
|
||||
# This feature turns on navigation elements in the footer that allow the
|
||||
# user to navigate to a next or previous page.
|
||||
# https://zensical.org/docs/setup/footer/#navigation
|
||||
"navigation.footer",
|
||||
|
||||
# When section index pages are enabled, documents can be directly attached
|
||||
# to sections, which is particularly useful for providing overview pages.
|
||||
# https://zensical.org/docs/setup/navigation/#section-index-pages
|
||||
"navigation.indexes",
|
||||
|
||||
# When instant navigation is enabled, clicks on all internal links will be
|
||||
# intercepted and dispatched via XHR without fully reloading the page.
|
||||
# https://zensical.org/docs/setup/navigation/#instant-navigation
|
||||
"navigation.instant",
|
||||
|
||||
# With instant prefetching, your site will start to fetch a page once the
|
||||
# user hovers over a link. This will reduce the perceived loading time
|
||||
# for the user.
|
||||
# https://zensical.org/docs/setup/navigation/#instant-prefetching
|
||||
"navigation.instant.prefetch",
|
||||
|
||||
# In order to provide a better user experience on slow connections when
|
||||
# using instant navigation, a progress indicator can be enabled.
|
||||
# https://zensical.org/docs/setup/navigation/#progress-indicator
|
||||
#"navigation.instant.progress",
|
||||
|
||||
# When navigation paths are activated, a breadcrumb navigation is rendered
|
||||
# above the title of each page
|
||||
# https://zensical.org/docs/setup/navigation/#navigation-path
|
||||
"navigation.path",
|
||||
|
||||
# When pruning is enabled, only the visible navigation items are included
|
||||
# in the rendered HTML, reducing the size of the built site by 33% or more.
|
||||
# https://zensical.org/docs/setup/navigation/#navigation-pruning
|
||||
#"navigation.prune",
|
||||
|
||||
# When sections are enabled, top-level sections are rendered as groups in
|
||||
# the sidebar for viewports above 1220px, but remain as-is on mobile.
|
||||
# https://zensical.org/docs/setup/navigation/#navigation-sections
|
||||
"navigation.sections",
|
||||
|
||||
# When tabs are enabled, top-level sections are rendered in a menu layer
|
||||
# below the header for viewports above 1220px, but remain as-is on mobile.
|
||||
# https://zensical.org/docs/setup/navigation/#navigation-tabs
|
||||
#"navigation.tabs",
|
||||
|
||||
# When sticky tabs are enabled, navigation tabs will lock below the header
|
||||
# and always remain visible when scrolling down.
|
||||
# https://zensical.org/docs/setup/navigation/#sticky-navigation-tabs
|
||||
#"navigation.tabs.sticky",
|
||||
|
||||
# A back-to-top button can be shown when the user, after scrolling down,
|
||||
# starts to scroll up again.
|
||||
# https://zensical.org/docs/setup/navigation/#back-to-top-button
|
||||
"navigation.top",
|
||||
|
||||
# When anchor tracking is enabled, the URL in the address bar is
|
||||
# automatically updated with the active anchor as highlighted in the table
|
||||
# of contents.
|
||||
# https://zensical.org/docs/setup/navigation/#anchor-tracking
|
||||
"navigation.tracking",
|
||||
|
||||
# When search highlighting is enabled and a user clicks on a search result,
|
||||
# Zensical will highlight all occurrences after following the link.
|
||||
# https://zensical.org/docs/setup/search/#search-highlighting
|
||||
"search.highlight",
|
||||
|
||||
# When anchor following for the table of contents is enabled, the sidebar
|
||||
# is automatically scrolled so that the active anchor is always visible.
|
||||
# https://zensical.org/docs/setup/navigation/#anchor-following
|
||||
# "toc.follow",
|
||||
|
||||
# When navigation integration for the table of contents is enabled, it is
|
||||
# always rendered as part of the navigation sidebar on the left.
|
||||
# https://zensical.org/docs/setup/navigation/#navigation-integration
|
||||
#"toc.integrate",
|
||||
]
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# You can configure your own logo to be shown in the header using the "logo"
|
||||
# option in the "theme" subsection. The logo must be a relative path to a file
|
||||
# in your "docs_dir", e.g., to use `docs/assets/logo.png` you would set:
|
||||
# ----------------------------------------------------------------------------
|
||||
logo = "assets/images/tree-ad-logo.svg"
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# If you don't have a dedicated project logo, you can use a built-in icon from
|
||||
# the icon sets shipped in Zensical. Please note that the setting lives in a
|
||||
# different subsection, and that the above take precedence over the icon.
|
||||
#
|
||||
# Read more:
|
||||
# - https://zensical.org/docs/setup/logo-and-icons
|
||||
# - https://github.com/zensical/ui/tree/master/dist/.icons
|
||||
# ----------------------------------------------------------------------------
|
||||
#[project.theme.icon]
|
||||
#logo = "lucide/smile"
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# In the "font" subsection you can configure the fonts used. By default, fonts
|
||||
# are loaded from Google Fonts, giving you a wide range of choices from a set
|
||||
# of suitably licensed fonts. There are options for a normal text font and for
|
||||
# a monospaced font used in code blocks.
|
||||
# ----------------------------------------------------------------------------
|
||||
#[project.theme.font]
|
||||
#text = "Inter"
|
||||
#code = "Jetbrains Mono"
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# In the "palette" subsection you can configure options for the color scheme.
|
||||
# You can configure different color schemes, e.g., to turn on dark mode,
|
||||
# that the user can switch between. Each color scheme can be further
|
||||
# customized.
|
||||
#
|
||||
# Read more:
|
||||
# - https://zensical.org/docs/setup/colors/
|
||||
# ----------------------------------------------------------------------------
|
||||
[[project.theme.palette]]
|
||||
scheme = "default"
|
||||
primary = "green"
|
||||
accent = "teal"
|
||||
toggle.icon = "lucide/sun"
|
||||
toggle.name = "Switch to dark mode"
|
||||
|
||||
[[project.theme.palette]]
|
||||
scheme = "slate"
|
||||
primary = "green"
|
||||
accent = "teal"
|
||||
toggle.icon = "lucide/moon"
|
||||
toggle.name = "Switch to light mode"
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# The "extra" section contains miscellaneous settings.
|
||||
# ----------------------------------------------------------------------------
|
||||
[project.extra.cusdis]
|
||||
host = "https://cusdis.krystl.org"
|
||||
app_id = "d9ab4b66-d5f1-4514-a475-1a824f69530f"
|
||||
lang = "en"
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Action Points — interactive checklist feature flag.
|
||||
# Set enabled = false to disable the ENTIRE feature (localStorage progress,
|
||||
# nav badges, heading pills, confetti, and all per-click JS). Checkboxes then
|
||||
# render as Material's default read-only tasklist. The flag is exposed to the
|
||||
# client via overrides/main.html as window.TOA_ACTION_POINTS_ENABLED.
|
||||
# ----------------------------------------------------------------------------
|
||||
[project.extra.action_points]
|
||||
enabled = true
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Keep In Touch — subscribe widget (rendered above comments on every page).
|
||||
# Captures a visitor's WhatsApp number and/or email (and later their name)
|
||||
# and POSTs them as JSON to `endpoint`. Set enabled = false to hide the
|
||||
# widget entirely. The endpoint is exposed to client JS as
|
||||
# window.TOA_KEEP_IN_TOUCH_ENDPOINT via overrides/main.html and as the
|
||||
# data-endpoint attribute on the widget (overrides/partials/keep-in-touch.html).
|
||||
# ----------------------------------------------------------------------------
|
||||
[project.extra.keep_in_touch]
|
||||
enabled = true
|
||||
endpoint = "https://subscribe.krystl.org/api/subscribe"
|
||||
|
||||
|
||||
#[[project.extra.social]]
|
||||
#icon = "fontawesome/brands/github"
|
||||
#link = "https://github.com/user/repo"
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# In this section you can configure the Markdown extensions that are used when
|
||||
# rendering your documentation. We enable the most useful extensions by default,
|
||||
# but you can customize this list to your needs.
|
||||
#
|
||||
# Read more:
|
||||
# - https://zensical.org/docs/setup/extensions/
|
||||
# ----------------------------------------------------------------------------
|
||||
[project.markdown_extensions.abbr]
|
||||
[project.markdown_extensions.admonition]
|
||||
[project.markdown_extensions.attr_list]
|
||||
[project.markdown_extensions.def_list]
|
||||
[project.markdown_extensions.footnotes]
|
||||
[project.markdown_extensions.md_in_html]
|
||||
[project.markdown_extensions.toc]
|
||||
permalink = true
|
||||
[project.markdown_extensions."_extensions.wikilinks:WikilinksExtension"]
|
||||
[project.markdown_extensions.pymdownx.arithmatex]
|
||||
generic = true
|
||||
[project.markdown_extensions.pymdownx.betterem]
|
||||
[project.markdown_extensions.pymdownx.caret]
|
||||
[project.markdown_extensions.pymdownx.details]
|
||||
[project.markdown_extensions.pymdownx.emoji]
|
||||
emoji_generator = "zensical.extensions.emoji.to_svg"
|
||||
emoji_index = "zensical.extensions.emoji.twemoji"
|
||||
[project.markdown_extensions.pymdownx.highlight]
|
||||
anchor_linenums = true
|
||||
line_spans = "__span"
|
||||
pygments_lang_class = true
|
||||
[project.markdown_extensions.pymdownx.inlinehilite]
|
||||
[project.markdown_extensions.pymdownx.keys]
|
||||
[project.markdown_extensions.pymdownx.magiclink]
|
||||
[project.markdown_extensions.pymdownx.mark]
|
||||
[project.markdown_extensions.pymdownx.smartsymbols]
|
||||
[project.markdown_extensions.pymdownx.superfences]
|
||||
custom_fences = [
|
||||
{ name = "mermaid", class = "mermaid", format = "pymdownx.superfences.fence_code_format" },
|
||||
]
|
||||
[project.markdown_extensions.pymdownx.tabbed]
|
||||
alternate_style = true
|
||||
combine_header_slug = true
|
||||
[project.markdown_extensions.pymdownx.tasklist]
|
||||
custom_checkbox = true
|
||||
[project.markdown_extensions.pymdownx.tilde]
|
||||