Skip to content

Commit 856a448

Browse files
feat: add listIndentKind config option (#176)
1 parent 0dea593 commit 856a448

7 files changed

Lines changed: 84 additions & 4 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

deployment/schema.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,18 @@
8484
"description": "Uses an underline of = or - beneath the heading text (setext headings). Only applies to level 1 and 2 headings."
8585
}]
8686
},
87+
"listIndentKind": {
88+
"description": "The style of indentation to use for list items. CommonMark aligns to the content column after the marker. PythonMarkdown uses a fixed 4-space indent, required by tools like mkdocs-material.",
89+
"type": "string",
90+
"default": "commonMark",
91+
"oneOf": [{
92+
"const": "commonMark",
93+
"description": "Indents continuation lines to align with the content after the list marker (e.g. 3 spaces for '1. ', 4 for '10. ')."
94+
}, {
95+
"const": "pythonMarkdown",
96+
"description": "Always indents by 4 spaces, regardless of marker width."
97+
}]
98+
},
8799
"deno": {
88100
"description": "Top level configuration that sets the configuration to what is used in Deno.",
89101
"type": "boolean",
@@ -125,6 +137,9 @@
125137
"headingKind": {
126138
"$ref": "#/definitions/headingKind"
127139
},
140+
"listIndentKind": {
141+
"$ref": "#/definitions/listIndentKind"
142+
},
128143
"deno": {
129144
"$ref": "#/definitions/deno"
130145
},

src/configuration/builder.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ impl ConfigurationBuilder {
8585
self.insert("headingKind", value.to_string().into())
8686
}
8787

88+
/// The style of list indentation to use.
89+
/// Default: `ListIndentKind::CommonMark`
90+
pub fn list_indent_kind(&mut self, value: ListIndentKind) -> &mut Self {
91+
self.insert("listIndentKind", value.to_string().into())
92+
}
93+
8894
/// The directive used to ignore a line.
8995
/// Default: `dprint-ignore`
9096
pub fn ignore_directive(&mut self, value: &str) -> &mut Self {
@@ -147,13 +153,14 @@ mod tests {
147153
.strong_kind(StrongKind::Underscores)
148154
.unordered_list_kind(UnorderedListKind::Asterisks)
149155
.heading_kind(HeadingKind::Atx)
156+
.list_indent_kind(ListIndentKind::PythonMarkdown)
150157
.ignore_directive("test")
151158
.ignore_file_directive("test")
152159
.ignore_start_directive("test")
153160
.ignore_end_directive("test");
154161

155162
let inner_config = config.get_inner_config();
156-
assert_eq!(inner_config.len(), 11);
163+
assert_eq!(inner_config.len(), 12);
157164
let diagnostics = resolve_config(inner_config, &Default::default()).diagnostics;
158165
assert_eq!(diagnostics.len(), 0);
159166
}

src/configuration/resolve_config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ pub fn resolve_config(
6565
&mut diagnostics,
6666
),
6767
heading_kind: get_value(&mut config, "headingKind", HeadingKind::Atx, &mut diagnostics),
68+
list_indent_kind: get_value(&mut config, "listIndentKind", ListIndentKind::CommonMark, &mut diagnostics),
6869
ignore_directive: get_value(
6970
&mut config,
7071
"ignoreDirective",

src/configuration/types.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub struct Configuration {
1616
pub strong_kind: StrongKind,
1717
pub unordered_list_kind: UnorderedListKind,
1818
pub heading_kind: HeadingKind,
19+
pub list_indent_kind: ListIndentKind,
1920
pub ignore_directive: String,
2021
pub ignore_file_directive: String,
2122
pub ignore_start_directive: String,
@@ -115,3 +116,20 @@ pub enum HeadingKind {
115116
}
116117

117118
generate_str_to_from![HeadingKind, [Setext, "setext"], [Atx, "atx"]];
119+
120+
/// The style of indentation to use for list items.
121+
///
122+
/// CommonMark aligns continuation lines to the content column after the marker
123+
/// (e.g. 3 spaces for `1. `, 4 spaces for `10. `). PythonMarkdown uses a fixed
124+
/// 4-space indent regardless of marker width, which is required by tools like
125+
/// mkdocs-material.
126+
#[derive(Clone, PartialEq, Copy, Serialize, Deserialize)]
127+
#[serde(rename_all = "camelCase")]
128+
pub enum ListIndentKind {
129+
/// Indents continuation lines to align with the content after the list marker (default).
130+
CommonMark,
131+
/// Always indents by 4 spaces, regardless of marker width.
132+
PythonMarkdown,
133+
}
134+
135+
generate_str_to_from![ListIndentKind, [CommonMark, "commonMark"], [PythonMarkdown, "pythonMarkdown"]];

src/generation/generate.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,10 @@ fn gen_list(list: &List, is_alternate: bool, context: &mut Context) -> PrintItem
741741
} else {
742742
String::from(context.configuration.unordered_list_kind.list_char(is_alternate))
743743
};
744-
let indent_increment = (prefix_text.chars().count() + 1) as u32;
744+
let indent_increment = match context.configuration.list_indent_kind {
745+
crate::configuration::ListIndentKind::CommonMark => (prefix_text.chars().count() + 1) as u32,
746+
crate::configuration::ListIndentKind::PythonMarkdown => std::cmp::max(prefix_text.chars().count() as u32 + 1, 4),
747+
};
745748
context.indent_level += indent_increment;
746749
items.push_string(prefix_text);
747750
let after_child = LineAndColumn::new("afterChild");
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
~~ listIndentKind: pythonMarkdown ~~
2+
!! should indent nested ordered list by 4 spaces !!
3+
1. first
4+
1. nested first
5+
2. nested second
6+
2. second
7+
8+
[expect]
9+
1. first
10+
1. nested first
11+
2. nested second
12+
2. second
13+
14+
!! should indent nested unordered list by 4 spaces !!
15+
- first
16+
- nested first
17+
- nested second
18+
- second
19+
20+
[expect]
21+
- first
22+
- nested first
23+
- nested second
24+
- second
25+
26+
!! should indent double-digit ordered list consistently !!
27+
9. Testing
28+
6. Test
29+
10. Other
30+
7. Testing
31+
32+
[expect]
33+
9. Testing
34+
6. Test
35+
10. Other
36+
7. Testing

0 commit comments

Comments
 (0)