mdbook_numbering/config.rs
1use serde::de::IgnoredAny;
2use serde::{Deserialize, Serialize};
3
4/// The numbering style to be used by the `mdbook-numbering` preprocessor.
5///
6/// Should be placed under the `numbering-style` field
7/// in the `[preprocessor.numbering]` section in `book.toml`.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
9#[non_exhaustive]
10#[serde(rename_all = "kebab-case")]
11#[serde(deny_unknown_fields)]
12pub enum NumberingStyle {
13 /// There should be no more than one top heading (the heading with the highest level)
14 /// in the chapter, and it should has the same level as the chapter numbering.
15 ///
16 /// For example, if the numbering of the chapter is `1.2.3`, the top heading in the chapter
17 /// should be level 3 (i.e., `### Chapter 1.2.3`).
18 ///
19 /// This is the default behavior of `mdbook-numbering`. And it works well with [mdbook-pdf]
20 /// in regard to generating the table of contents.
21 ///
22 /// [mdbook-pdf]: https://github.com/HollowMan6/mdbook-pdf
23 Consecutive,
24 /// There should be no more than one top heading (the heading with the highest level)
25 /// in the chapter, and it should be level 1 (i.e., `# Chapter 1.2.3`),
26 /// regardless of the chapter numbering.
27 ///
28 /// This style is more flexible, but may lead to inconsistent heading levels across chapters.
29 /// And using it you may get a flat table of contents when generating PDF with [mdbook-pdf].
30 ///
31 /// By the way, this is how [the documentation of mdbook] is structured.
32 ///
33 /// [mdbook-pdf]: https://github.com/HollowMan6/mdbook-pdf
34 /// [the documentation of mdbook]: https://github.com/rust-lang/mdBook/tree/master/guide
35 Top,
36 // Future numbering styles can be added here.
37}
38
39impl NumberingStyle {
40 /// Create a new `NumberingStyle` with default value.
41 pub const fn new() -> Self {
42 Self::Consecutive
43 }
44}
45
46impl Default for NumberingStyle {
47 fn default() -> Self {
48 Self::new()
49 }
50}
51
52fn bool_true() -> bool {
53 true
54}
55
56/// Configuration for heading numbering style.
57///
58/// Should be placed under the `heading` field
59/// in the `[preprocessor.numbering]` section in `book.toml`.
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
61#[non_exhaustive]
62#[serde(rename_all = "kebab-case")]
63#[serde(deny_unknown_fields)]
64pub struct HeadingConfig {
65 /// Whether to enable heading numbering.
66 #[serde(default = "bool_true")]
67 pub enable: bool,
68 /// Whether to treat warnings as errors.
69 #[serde(default)]
70 pub numbering_style: NumberingStyle,
71 // Future configuration options can be added here.
72}
73
74impl HeadingConfig {
75 /// Create a new `HeadingConfig` with default values.
76 pub const fn new() -> Self {
77 Self {
78 enable: true,
79 numbering_style: NumberingStyle::new(),
80 }
81 }
82}
83
84impl Default for HeadingConfig {
85 fn default() -> Self {
86 Self::new()
87 }
88}
89
90/// Configuration for code block line numbering.
91///
92/// Should be placed under the `code` field
93/// in the `[preprocessor.numbering]` section in `book.toml`.
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
95#[non_exhaustive]
96#[serde(rename_all = "kebab-case")]
97#[serde(deny_unknown_fields)]
98pub struct CodeConfig {
99 /// Whether to enable code numbering.
100 #[serde(default = "bool_true")]
101 pub enable: bool,
102 // Future configuration options can be added here.
103}
104
105impl CodeConfig {
106 /// Create a new `CodeConfig` with default values.
107 pub const fn new() -> Self {
108 Self { enable: true }
109 }
110}
111
112impl Default for CodeConfig {
113 fn default() -> Self {
114 Self::new()
115 }
116}
117
118/// Configuration for the `mdbook-numbering` preprocessor.
119///
120/// Should be placed under the `[preprocessor.numbering]` section in `book.toml`.
121#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
122#[non_exhaustive]
123#[serde(rename_all = "kebab-case")]
124#[serde(deny_unknown_fields)]
125pub struct NumberingConfig {
126 /// Those preprocessors that `mdbook-numbering` should run after.
127 #[serde(default, skip_serializing)]
128 pub after: IgnoredAny,
129 /// Those preprocessors that `mdbook-numbering` should run before.
130 #[serde(default, skip_serializing)]
131 pub before: IgnoredAny,
132 /// Configuration for line numbering in code blocks.
133 #[serde(default)]
134 pub code: CodeConfig,
135 /// Placeholder to ignore unused fields.
136 #[serde(default, skip_serializing)]
137 pub command: IgnoredAny,
138 /// Configuration for heading numbering.
139 #[serde(default)]
140 pub heading: HeadingConfig,
141 /// Placeholder to ignore unused fields.
142 #[serde(default, skip_serializing)]
143 pub optional: IgnoredAny,
144 /// Placeholder to ignore unused fields.
145 #[serde(default, skip_serializing)]
146 pub renderers: IgnoredAny,
147 // Future configuration options can be added here.
148}
149
150impl NumberingConfig {
151 /// Create a new `NumberingConfig` with default values.
152 pub const fn new() -> Self {
153 Self {
154 after: IgnoredAny,
155 before: IgnoredAny,
156 code: CodeConfig::new(),
157 command: IgnoredAny,
158 heading: HeadingConfig::new(),
159 optional: IgnoredAny,
160 renderers: IgnoredAny,
161 }
162 }
163}
164
165impl Default for NumberingConfig {
166 fn default() -> Self {
167 Self::new()
168 }
169}
170
171impl PartialEq for NumberingConfig {
172 fn eq(&self, other: &Self) -> bool {
173 self.code == other.code && self.heading == other.heading
174 }
175}
176impl Eq for NumberingConfig {}