Skip to content

Commit 2d34f26

Browse files
doudenLjon4ik4
andauthored
Prepare release (#166)
**Added** - Options for customizing proof directive title format. [#163](#163) - Possibility for shared numbering of groups of directives, fixing [\#64](#64). [\#https://github.com/executablebooks/sphinx-proof/pull/161](https://github.com/executablebooks/sphinx-proof/pull/161) **Fixed** - Inconsistencies and missing colors within CSS styles. [b337c21](b337c21) - Missing documentation for notation directive. [6f33744](6f33744) and [b15c7c0](b15c7c0) - Nesting of unnumbered directives, fixing [\#165](#165). --------- Co-authored-by: Leonid Ryvkin <ryvkin@gmx.com>
1 parent 97cfc7b commit 2d34f26

14 files changed

Lines changed: 460 additions & 96 deletions

File tree

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Added
6+
7+
- Options for customizing proof directive title format. [#163](https://github.com/executablebooks/sphinx-proof/pull/163)
8+
- Possibility for shared numbering of groups of directives, fixing [\#64](https://github.com/executablebooks/sphinx-proof/issues/64). [\#https://github.com/executablebooks/sphinx-proof/pull/161](https://github.com/executablebooks/sphinx-proof/pull/161)
9+
10+
### Fixed
11+
12+
- Inconsistencies and missing colors within CSS styles. [b337c21](https://github.com/executablebooks/sphinx-proof/commit/b337c21675464224a4418beb9e70d3b6dc8e4127)
13+
- Missing documentation for notation directive. [6f33744](https://github.com/executablebooks/sphinx-proof/commit/6f33744544b7596a30beba5b8807491d642b77a7) and [b15c7c0](https://github.com/executablebooks/sphinx-proof/commit/b15c7c09adefe85e0fdb8dea6dc460bd0f51fb1f)
14+
- Nesting of unnumbered directives, fixing [\#165](https://github.com/executablebooks/sphinx-proof/issues/165).
15+
316
## v0.3.0 (2025-10-20)
417

518
### NEW ✨

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@
1010

1111
This package contains a [Sphinx](http://www.sphinx-doc.org/) extension
1212
for producing proof, theorem, axiom, lemma, definition, criterion, remark, conjecture,
13-
corollary, algorithm, example, property, observation, proposition and assumption directives.
13+
corollary, algorithm, example, property, observation, proposition, assumption and notation directives.
1414

1515
## Features
1616

1717
- **15 directive types** for mathematical proofs and theorems
1818
- **Automatic numbering** of directives
19+
- optional shared numbering of groups of directives
1920
- **Cross-referencing** support via `prf:ref` role
2021
- **33 languages supported** - Complete translations for all directive types in English plus 32 additional languages (Arabic, Bengali, Bulgarian, Chinese, Czech, Danish, Dutch, Finnish, French, German, Greek, Hebrew, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean, Malay, Norwegian, Persian, Polish, Portuguese, Romanian, Russian, Spanish, Swedish, Thai, Turkish, Ukrainian, Urdu, Vietnamese)
21-
- **Customizable styling** with multiple theme options
22-
22+
- **Customizable styling** with:
23+
- two theme options
24+
- directive title format customization
2325

2426
## Get started
2527

docs/source/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,5 @@
5656
# MyST Parser Configuration
5757

5858
myst_enable_extensions = ["dollarmath", "amsmath"]
59+
60+
prf_realtyp_to_countertyp = {}

docs/source/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ for producing [proof](syntax:proof), [theorem](syntax:theorem), [axiom](syntax:a
2222
[definition](syntax:definition), [criterion](syntax:criterion), [remark](syntax:remark),
2323
[conjecture](syntax:conjecture),[corollary](syntax:corollary), [algorithm](syntax:algorithm),
2424
[example](syntax:example), [property](syntax:property), [observation](syntax:observation),
25-
[proposition](syntax:proposition) and [assumption](syntax:assumption) directives.
25+
[proposition](syntax:proposition), [assumption](syntax:assumption) and [notation](syntax:notation) directives.
2626

2727
**Features**:
2828

docs/source/options.md

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Options
22

3+
## Minimal color scheme
4+
35
This package has the option to choose a more **minimal** color scheme.
46

57
The aim is to create admonitions that are clearly different to the core text with
@@ -15,7 +17,7 @@ compared to the current default
1517

1618
To enable the `minimal` color scheme you can use the following.
1719

18-
## Jupyter Book Project
20+
### Jupyter Book Project
1921

2022
Add `proof_minimal_theme = True` to your `_config.yml`
2123

@@ -25,6 +27,112 @@ sphinx:
2527
proof_minimal_theme: true
2628
```
2729
28-
## Sphinx Project
30+
### Sphinx Project
2931
3032
Add `proof_minimal_theme = True` to your `conf.py`
33+
34+
## Shared numbering
35+
36+
By default, each type of (prf-)directive has their own numbering and counter. This can be changed by setting the option `prf_realtyp_to_countertyp` to a dictionary associating to a directive which the counter of which directive it should use.
37+
38+
### Sphinx Project
39+
40+
In `conf.py`, e.g. to have a shared counter for all directives:
41+
42+
```
43+
prf_realtyp_to_countertyp = {
44+
"axiom": "theorem",
45+
"theorem": "theorem",
46+
"lemma": "theorem",
47+
"algorithm": "theorem",
48+
"definition": "theorem",
49+
"remark": "theorem",
50+
"conjecture": "theorem",
51+
"corollary": "theorem",
52+
"criterion": "theorem",
53+
"example": "theorem",
54+
"property": "theorem",
55+
"observation": "theorem",
56+
"proposition": "theorem",
57+
"assumption": "theorem",
58+
"notation": "theorem",
59+
}
60+
```
61+
62+
In the following case, the directives `lemma`, `conjecture`, `corollary` and `proposition` will share the counter with `theorem`, while `axiom` and `assumption` will share the counter with `definition`. All other directives would use their original counter.
63+
64+
65+
```
66+
prf_realtyp_to_countertyp = {
67+
"lemma": "theorem",
68+
"conjecture": "theorem",
69+
"corollary": "theorem",
70+
"proposition": "theorem",
71+
"axiom": "definition",
72+
"assumption": "definition",
73+
}
74+
```
75+
76+
````{warning}
77+
The association of a counter to a directive is not transitive: Let us consider the following configuration:
78+
79+
```
80+
prf_realtyp_to_countertyp = {
81+
"lemma": "theorem",
82+
"conjecture": "lemma",
83+
}
84+
```
85+
86+
The `lemma` and `theorem` directives share a counter, however the `conjecture` directive has a separate counter (the `lemma` counter which is **not** used by `lemma` directives).
87+
````
88+
89+
## Title format
90+
91+
By default, the directive titles are formatted as `Name x.y.z (Title)`, where `Name` is the name of the directive (e.g., Proof, Theorem, Definition), `x.y.z` is the numbering of the directive, and `Title` is the optional title provided by the user.
92+
93+
If no title is provided, only `Name x.y.z` is displayed.
94+
95+
The font weight of the entire title (`Name x.y.z (Title)` or `Name x.y.z`) is set to `--pst-admonition-font-weight-heading` by default, which commonly results in a semi-bold appearance.
96+
97+
In the reminder we call the part `Name x.y.z` the "number" and the part `(Title)` the "title".
98+
99+
You can customize the title format using the `proof_title_format` option:
100+
101+
- This option allows you to define how the title should be displayed by using `%t` as a placeholder for the user-provided title.
102+
- The default format is ` (%t)`.
103+
- A value of an empty string will result in no title being displayed.
104+
- A `markdown` string can be used to format the title.
105+
- For example, ` *%t*` will emphasize the title and contain no brackets.
106+
107+
Note that the initial part of the title (i.e., `Name x.y.z`) is not customizable and will always be displayed.
108+
109+
The font weight of the title can be adjusted using the `proof_title_weight` option:
110+
111+
- Any valid CSS font-weight value can be used, such as `normal`, `bold`, `bolder`, `lighter`, or numeric values like `400`, `700`, etc.
112+
- Default value is `var(--pst-admonition-font-weight-heading)`.
113+
114+
The font weight of the number can be adjusted using the `proof_number_weight` option:
115+
- Any valid CSS font-weight value can be used, such as `normal`, `bold`, `bolder`, `lighter`, or numeric values like `400`, `700`, etc.
116+
- Default value is `var(--pst-admonition-font-weight-heading)`.
117+
118+
### Jupyter Book Project
119+
120+
Add `proof_title_format`, `proof_number_weight` and/or `proof_title_weight` to your `_config.yml`
121+
122+
```yaml
123+
sphinx:
124+
config:
125+
proof_title_format: " *%t*"
126+
proof_number_weight: "bold"
127+
proof_title_weight: "normal"
128+
```
129+
130+
### Sphinx Project
131+
132+
Add `proof_title_format`, `proof_number_weight` and/or `proof_title_weight` to your `conf.py`
133+
134+
```python
135+
proof_title_format = " *%t*"
136+
proof_number_weight = "bold"
137+
proof_title_weight = "normal"
138+
```

docs/source/syntax.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,43 @@ This is a dummy assumption directive.
749749

750750
You can refer to an assumption using the `{prf:ref}` role like: ```{prf:ref}`my-assumption` ```, which will replace the reference with the assumption number like so: {prf:ref}`my-assumption`. When an explicit text is provided, this caption will serve as the title of the reference.
751751

752+
(syntax:notation)=
753+
### Notations
754+
755+
A notation directive can be included using the `prf:notation` pattern. The directive is enumerated by default and can take in an optional title argument. The following options are also supported:
756+
757+
* `label` : text
758+
759+
A unique identifier for your notation that you can use to reference it with `{prf:ref}`. Cannot contain spaces or special characters.
760+
* `class` : text
761+
762+
Value of the notation’s class attribute which can be used to add custom CSS or JavaScript.
763+
* `nonumber` : flag (empty)
764+
765+
Turns off notation auto numbering.
766+
767+
**Example**
768+
769+
```{prf:notation}
770+
:label: my-notation
771+
772+
This is a dummy notation directive.
773+
```
774+
775+
**MyST Syntax**
776+
777+
``````md
778+
```{prf:notation}
779+
:label: my-notation
780+
781+
This is a dummy notation directive.
782+
```
783+
``````
784+
785+
#### Referencing Notations
786+
787+
You can refer to a notation using the `{prf:ref}` role like: ```{prf:ref}`my-notation` ```, which will replace the reference with the notation number like so: {prf:ref}`my-notation`. When an explicit text is provided, this caption will serve as the title of the reference.
788+
752789
## How to Hide Content
753790

754791
Directive content can be hidden using the `dropdown` class which is available through [sphinx-togglebutton](https://sphinx-togglebutton.readthedocs.io/en/latest/). If your project utilizes the [MyST-NB](https://myst-nb.readthedocs.io/en/latest/) extension, there is no need to activate `sphinx-togglebutton` since it is already bundled with `MyST-NB`.

sphinx_proof/__init__.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,39 @@ def copy_asset_files(app: Sphinx, exc: Union[bool, Exception]):
7676
if exc is None:
7777
for path in asset_files:
7878
copy_asset(path, str(Path(app.outdir).joinpath("_static").absolute()))
79+
# if needed, load css to memory,
80+
# adjust font-weight according to user's setting in config
81+
# and write to output static file
82+
if app.config.proof_number_weight or app.config.proof_title_weight:
83+
# only if at least one of the two options is set
84+
path = str(Path(app.outdir).joinpath("_static", "proof.css").absolute())
85+
with open(path, "r", encoding="utf-8") as f:
86+
css_content = f.read()
87+
if app.config.proof_number_weight:
88+
css_content = css_content.replace(
89+
"div.proof > p.admonition-title > span.caption-number {\n font-weight: var(--pst-admonition-font-weight-heading);\n}", # noqa: E501
90+
f"div.proof > p.admonition-title > span.caption-number {{\n font-weight: {app.config.proof_number_weight};\n}}", # noqa: E501
91+
)
92+
if app.config.proof_title_weight:
93+
css_content = css_content.replace(
94+
"div.proof > p.admonition-title {\n font-weight: var(--pst-admonition-font-weight-heading);\n}", # noqa: E501
95+
f"div.proof > p.admonition-title {{\n font-weight: {app.config.proof_title_weight};\n}}", # noqa: E501
96+
)
97+
out_path = Path(app.outdir).joinpath("_static", os.path.basename(path))
98+
with open(out_path, "w", encoding="utf-8") as f:
99+
f.write(css_content)
79100

80101

81102
def setup(app: Sphinx) -> Dict[str, Any]:
82103

83104
app.add_config_value("proof_minimal_theme", False, "html")
105+
app.add_config_value("prf_realtyp_to_countertyp", {}, "html")
106+
app.add_config_value("proof_title_format", " (%t)", "html")
107+
app.add_config_value("proof_number_weight", "", "html")
108+
app.add_config_value("proof_title_weight", "", "html")
84109

85110
app.add_css_file("proof.css")
111+
app.connect("config-inited", check_config_values)
86112
app.connect("build-finished", copy_asset_files)
87113
app.connect("config-inited", init_numfig)
88114
app.connect("env-purge-doc", purge_proofs)
@@ -118,3 +144,64 @@ def setup(app: Sphinx) -> Dict[str, Any]:
118144
"parallel_read_safe": True,
119145
"parallel_write_safe": True,
120146
}
147+
148+
149+
def check_config_values(app: Sphinx, config: Config) -> None:
150+
"""Check configuration values."""
151+
# Check if proof_minimal_theme is boolean
152+
if not isinstance(config.proof_minimal_theme, bool):
153+
logger.warning(
154+
"'proof_minimal_theme' config value must be a boolean. "
155+
"Using default value False."
156+
)
157+
config.proof_minimal_theme = False
158+
159+
# Check of prf_realtyp_to_countertyp is a dictionary
160+
if not isinstance(config.prf_realtyp_to_countertyp, dict):
161+
logger.warning(
162+
"'prf_realtyp_to_countertyp' config value must be a dictionary. "
163+
"Using default empty dictionary."
164+
)
165+
config.prf_realtyp_to_countertyp = {}
166+
# Check if each key and each value in prf_realtyp_to_countertyp
167+
# is a valid proof type
168+
for key, value in config.prf_realtyp_to_countertyp.items():
169+
if key not in PROOF_TYPES:
170+
logger.warning(
171+
f"Key '{key}' in 'prf_realtyp_to_countertyp' is not "
172+
"a valid proof type. "
173+
"It will be removed."
174+
)
175+
del config.prf_realtyp_to_countertyp[key]
176+
elif value not in PROOF_TYPES:
177+
logger.warning(
178+
f"Value '{value}' in 'prf_realtyp_to_countertyp' is not "
179+
"a valid proof type. It will be removed."
180+
)
181+
del config.prf_realtyp_to_countertyp[key]
182+
# Check if proof_title_format is a string
183+
if not isinstance(config.proof_title_format, str):
184+
logger.warning(
185+
"'proof_title_format' config value must be a string."
186+
"Using default value ' (%t)'."
187+
)
188+
config.proof_title_format = " (%t)"
189+
elif "%t" not in config.proof_title_format:
190+
logger.warning(
191+
"'proof_title_format' config value must contain the "
192+
"substring '%t' to print a title."
193+
)
194+
# Check if proof_number_weight is a string
195+
if not isinstance(config.proof_number_weight, str):
196+
logger.warning(
197+
"'proof_number_weight' config value must be a string. "
198+
"Using default value ''."
199+
)
200+
config.proof_number_weight = ""
201+
# Check if proof_title_weight is a string
202+
if not isinstance(config.proof_title_weight, str):
203+
logger.warning(
204+
"'proof_title_weight' config value must be a string. "
205+
"Using default value ''."
206+
)
207+
config.proof_title_weight = ""

sphinx_proof/_static/minimal/proof.css

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
--corollary-border-color: #c500c1;
1313
--example-border-color: #f9377b;
1414
--property-border-color: #fdf914;
15-
--obseration-border-color: #7707ff;
15+
--observation-border-color: #7707ff;
1616
--proposition-border-color: #4f7aa8;
1717
--assumption-border-color: #07fffb;
18+
--notation-border-color: rgb(0, 255, 200);
1819

1920
/* --note-title-color: rgba(68,138,255,.1);
2021
--note-border-color: #007bff;
@@ -38,6 +39,15 @@ div.proof > .admonition-title::before {
3839
content: none;
3940
}
4041

42+
/* Set font weights */
43+
div.proof > p.admonition-title {
44+
font-weight: var(--pst-admonition-font-weight-heading) !important;
45+
}
46+
47+
div.proof > p.admonition-title > span.caption-number {
48+
font-weight: var(--pst-admonition-font-weight-heading) !important;
49+
}
50+
4151
/*********************************************
4252
* Proof *
4353
*********************************************/
@@ -209,6 +219,7 @@ div.proposition {
209219
div.proposition > .admonition-title {
210220
background-color: transparent;
211221
}
222+
212223
/*********************************************
213224
* Assumption *
214225
*********************************************/
@@ -220,3 +231,15 @@ div.assumption {
220231
div.assumption > .admonition-title {
221232
background-color: transparent;
222233
}
234+
235+
/*********************************************
236+
* Notation *
237+
*********************************************/
238+
div.notation {
239+
border-color: var(--notation-border-color);
240+
background-color: none;
241+
}
242+
243+
div.notation > .admonition-title {
244+
background-color: transparent;
245+
}

0 commit comments

Comments
 (0)