zensical-vars
Let readers put their own values into your examples. Declare a few fields on a page, reference them in code blocks and prose, and every reference updates as the reader types.
Note: This is an unoffical zensical plugin, and this project was entirely vibe (or slop) coded by Claude.
```zvars
- name: host
label: Server address
default: 192.168.1.1
- name: user
label: Username
default: my-user
```
```bash
ssh <<user>>@<<host>>
```
By providing default values, pages render with ssh my-user@192.168.1.1. A reader who enters 10.0.4.20 updates the doc content to ssh my-user@10.0.4.20. Defaults are substituted when users modify the value time, so the page even reads correctly with JavaScript disabled.
Install
This plugin has been tested with zensical version 0.0.55.
pip install zensical-vars
zensical-vars install docs
The second command copies the stylesheet and script into your docs directory,
where they sit like any other customization. Then register all three pieces in
zensical.toml:
[project]
extra_css = ["stylesheets/zensical-vars.css"]
extra_javascript = ["javascripts/zensical-vars.js"]
[project.markdown_extensions.zensical_vars]
type = "example"
Projects still carrying a YAML config can use the equivalent keys there, since Zensical reads that format natively:
markdown_extensions:
- zensical_vars
extra_css:
- stylesheets/zensical-vars.css
extra_javascript:
- javascripts/zensical-vars.js
Keep any other markdown_extensions you already have in that list, since naming the key can replace Zensical's defaults. Re-run zensical-vars install after upgrading to refresh the assets.
Declaring fields
Fields are declared per page in a fenced zvars block, which renders as the panel of inputs. Put it where you want the panel to appear.
Shorthand, when a name and a default are all you need:
host: 192.168.1.1
user: my-user
Full form, with panel options under a fields key:
title: Point these examples at your own server
collapsible: true # fold the panel away
open: false # ...and start it collapsed
panel: false # declare the fields, render no panel
fields:
- name: host
default: 192.168.1.1
help: The machine you are connecting to.
- name: port
default: 22
type: number # text, number, password, email, url, tel, search
- name: shell
default: bash
options: [bash, zsh, fish]
Referencing values
Write <<name>> in fenced code, inline code, tables, admonitions, tabbed content, link targets or plain prose. Escape a literal with a backslash: \<<host>>. Declare the same name on several pages and a reader's value follows them across the site.
Options
| Option | Default | What it does |
|---|---|---|
start / end |
<< / >> |
Reference delimiters. |
block |
zvars |
Info string of the declaration fence. |
title |
Use your own values |
Panel heading. |
note |
see source | Tooltip on the info icon. "" hides the icon. |
reset_label |
Reset to defaults |
Accessible label of the reset button. |
style |
admonition |
admonition uses a theme card; card restyles its chrome. |
type |
example |
Admonition type supplying the icon and colour scheme. |
collapsible |
false |
Render the panel as a collapsible <details>. |
open |
true |
Whether a collapsible panel starts expanded. |
persist |
true |
Remember values across pages in the browser. |
storage_key |
zensical-vars |
localStorage key used for that. |
panel |
true |
Block only. false declares the fields but renders no panel. |
Every option except panel can be set once in your configuration and overridden per block:
markdown_extensions:
- zensical_vars:
type: tip
collapsible: true
The panel
The panel is a theme admonition — the same markup an !!! example block produces — so its card, beaker icon and colour scheme come from the theme and follow your palette and colour schemes without configuration. Set type to any other admonition kind to change the icon and colour, or style: card for a flatter variant with a hairline border and a code-toned background.
collapsible: true emits a <details>, exactly as ??? example would, with the theme's own collapse control.
Text fields start empty, showing their default as placeholder text, so a reader types straight over it. Clearing a field returns it to the default, meaning the page can never show a blank value.
How it works
A reference can't simply be replaced with HTML, because by the time a code block reaches the page the highlighter has already split it into <span> tokens. So it runs in two stages: a preprocessor swaps each <<name>> for an all-letter sentinel that highlighters treat as an ordinary identifier, then a postprocessor swaps sentinels for live spans in the finished HTML — including inside a Pygments string token.
The extension emits page content and nothing else. The stylesheet and script are ordinary assets, loaded once per site and cached, and the script subscribes to the document$ observable so it rebinds on instant navigation.
Limitations
- A reference inside an HTML attribute —
[admin](http://<<host>>/)— renders with its default and doesn't update live. Nothing breaks; the link just stays pointed at the default. - Fields must be declared on the page that uses them. Use
panel: falseto declare without rendering a panel. - An undeclared reference is left exactly as written and logged as a build warning, so
std::cout << x >> ypasses through untouched.
Development
pip install -e ".[dev]"
pytest
black . # formatting
ruff check . # linting
The suite tests this extension, not Zensical: every test renders Markdown directly and asserts on the HTML, so no site build is involved and a bug in any downstream renderer cannot turn the build red.
Both tools are pinned in the dev extra so local runs match CI exactly. Black owns formatting at its default 88 columns; ruff lints only, configured to the same width so E501 and the formatter can never disagree.
The suite covers substitution inside every fence implementation, literal passthrough, escaping, panel markup, the asset installer, and a real Zensical build. CI runs it across Python 3.9–3.13 and against each supported Python-Markdown minor version, since the extension depends on processor priorities relative to the fenced-code and raw-HTML stages.
Licence
MIT.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zensical_vars-1.1.0.tar.gz.
File metadata
- Download URL: zensical_vars-1.1.0.tar.gz
- Upload date:
- Size: 25.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df6c12a4f845f298a9e656184038a581c7b5ad967b42f123241b246439a648be
|
|
| MD5 |
5392fc36c5c49297326e5b96f0ffaf92
|
|
| BLAKE2b-256 |
955ddf58c52ee7aaa5fc307ca6c77a4be2bdae9c1860c368226f74abb47a9da7
|
Provenance
The following attestation bundles were made for zensical_vars-1.1.0.tar.gz:
Publisher:
release.yml on 5tingy/zensical-vars
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zensical_vars-1.1.0.tar.gz -
Subject digest:
df6c12a4f845f298a9e656184038a581c7b5ad967b42f123241b246439a648be - Sigstore transparency entry: 2538768975
- Sigstore integration time:
-
Permalink:
5tingy/zensical-vars@3e46e350925a9d0ff77e09ad95a15c49e5d64b21 -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/5tingy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3e46e350925a9d0ff77e09ad95a15c49e5d64b21 -
Trigger Event:
push
-
Statement type:
File details
Details for the file zensical_vars-1.1.0-py3-none-any.whl.
File metadata
- Download URL: zensical_vars-1.1.0-py3-none-any.whl
- Upload date:
- Size: 18.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f0ecebb5adae7d1129bd8cc9fcde3f7470060466f4cd8ff6ad10f72529635e3c
|
|
| MD5 |
4019dacc248291de231427239f253993
|
|
| BLAKE2b-256 |
6c6c2bc6db492f2e9d3ff8d419320e00f69f7d38c0494591042b184e934847f9
|
Provenance
The following attestation bundles were made for zensical_vars-1.1.0-py3-none-any.whl:
Publisher:
release.yml on 5tingy/zensical-vars
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zensical_vars-1.1.0-py3-none-any.whl -
Subject digest:
f0ecebb5adae7d1129bd8cc9fcde3f7470060466f4cd8ff6ad10f72529635e3c - Sigstore transparency entry: 2538769920
- Sigstore integration time:
-
Permalink:
5tingy/zensical-vars@3e46e350925a9d0ff77e09ad95a15c49e5d64b21 -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/5tingy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3e46e350925a9d0ff77e09ad95a15c49e5d64b21 -
Trigger Event:
push
-
Statement type: