Skip to content

Commit 6242c41

Browse files
committed
docs(oxfmt): Add markdownDescription fields and unify the schema generation process.
With this change, the descriptions for each field in the JSON schema are rendered with proper markdown formatting in VS Code and other editors based on VS Code. This now matches the implementation for the Oxlintrc schema generation.
1 parent f6595c8 commit 6242c41

File tree

4 files changed

+132
-49
lines changed

4 files changed

+132
-49
lines changed

crates/oxc_formatter/src/service/oxfmtrc.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::path::Path;
22

3-
use schemars::JsonSchema;
3+
use schemars::{JsonSchema, schema_for};
44
use serde::{Deserialize, Deserializer, Serialize};
55

66
use crate::{
@@ -391,6 +391,60 @@ impl Oxfmtrc {
391391

392392
Ok(options)
393393
}
394+
395+
/// Generates the JSON schema for Oxfmtrc configuration files.
396+
///
397+
/// # Panics
398+
/// Panics if the schema generation fails.
399+
pub fn generate_schema_json() -> String {
400+
let mut schema = schema_for!(Oxfmtrc);
401+
402+
// Allow comments and trailing commas for vscode-json-languageservice
403+
// NOTE: This is NOT part of standard JSON Schema specification
404+
// https://github.com/microsoft/vscode-json-languageservice/blob/fb83547762901f32d8449d57e24666573016b10c/src/jsonLanguageTypes.ts#L151-L159
405+
schema.schema.extensions.insert("allowComments".to_string(), serde_json::Value::Bool(true));
406+
schema
407+
.schema
408+
.extensions
409+
.insert("allowTrailingCommas".to_string(), serde_json::Value::Bool(true));
410+
411+
// Inject markdownDescription fields for better editor support (e.g., VS Code)
412+
let mut json = serde_json::to_value(&schema).unwrap();
413+
Self::inject_markdown_descriptions(&mut json);
414+
415+
serde_json::to_string_pretty(&json).unwrap()
416+
}
417+
418+
/// Recursively inject `markdownDescription` fields into the JSON schema.
419+
/// This is a non-standard field that some editors (like VS Code) use to render
420+
/// markdown in hover tooltips.
421+
fn inject_markdown_descriptions(value: &mut serde_json::Value) {
422+
match value {
423+
serde_json::Value::Object(map) => {
424+
// If this object has a `description` field, copy it to `markdownDescription`
425+
if let Some(serde_json::Value::String(desc_str)) = map.get("description") {
426+
map.insert(
427+
"markdownDescription".to_string(),
428+
serde_json::Value::String(desc_str.clone()),
429+
);
430+
}
431+
432+
// Recursively process all values in the object
433+
for value in map.values_mut() {
434+
Self::inject_markdown_descriptions(value);
435+
}
436+
}
437+
serde_json::Value::Array(items) => {
438+
// Recursively process all items in the array
439+
for item in items {
440+
Self::inject_markdown_descriptions(item);
441+
}
442+
}
443+
_ => {
444+
// Primitive values don't need processing
445+
}
446+
}
447+
}
394448
}
395449

396450
// ---

crates/oxc_formatter/tests/schema.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,7 @@ use project_root::get_project_root;
88
#[test]
99
fn test_schema_json() {
1010
let path = get_project_root().unwrap().join("npm/oxfmt/configuration_schema.json");
11-
let mut schema = schemars::schema_for!(Oxfmtrc);
12-
// Allow comments and trailing commas for vscode-json-languageservice
13-
// NOTE: This is NOT part of standard JSON Schema specification
14-
// https://github.com/microsoft/vscode-json-languageservice/blob/fb83547762901f32d8449d57e24666573016b10c/src/jsonLanguageTypes.ts#L151-L159
15-
schema.schema.extensions.insert("allowComments".to_string(), serde_json::Value::Bool(true));
16-
schema
17-
.schema
18-
.extensions
19-
.insert("allowTrailingCommas".to_string(), serde_json::Value::Bool(true));
20-
let json = serde_json::to_string_pretty(&schema).unwrap();
11+
let json = Oxfmtrc::generate_schema_json();
2112
let existing_json = fs::read_to_string(&path).unwrap_or_default();
2213
if existing_json.trim() != json.trim() {
2314
std::fs::write(&path, &json).unwrap();

crates/oxc_formatter/tests/snapshots/schema_json.snap

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,24 @@ expression: json
1717
{
1818
"type": "null"
1919
}
20-
]
20+
],
21+
"markdownDescription": "Include parentheses around a sole arrow function parameter. (Default: `\"always\"`)"
2122
},
2223
"bracketSameLine": {
2324
"description": "Put the `>` of a multi-line JSX element at the end of the last line\ninstead of being alone on the next line. (Default: `false`)",
2425
"type": [
2526
"boolean",
2627
"null"
27-
]
28+
],
29+
"markdownDescription": "Put the `>` of a multi-line JSX element at the end of the last line\ninstead of being alone on the next line. (Default: `false`)"
2830
},
2931
"bracketSpacing": {
3032
"description": "Print spaces between brackets in object literals. (Default: `true`)",
3133
"type": [
3234
"boolean",
3335
"null"
34-
]
36+
],
37+
"markdownDescription": "Print spaces between brackets in object literals. (Default: `true`)"
3538
},
3639
"embeddedLanguageFormatting": {
3740
"description": "Control whether formats quoted code embedded in the file. (Default: `\"auto\"`)",
@@ -42,7 +45,8 @@ expression: json
4245
{
4346
"type": "null"
4447
}
45-
]
48+
],
49+
"markdownDescription": "Control whether formats quoted code embedded in the file. (Default: `\"auto\"`)"
4650
},
4751
"endOfLine": {
4852
"description": "Which end of line characters to apply. (Default: `\"lf\"`)",
@@ -53,7 +57,8 @@ expression: json
5357
{
5458
"type": "null"
5559
}
56-
]
60+
],
61+
"markdownDescription": "Which end of line characters to apply. (Default: `\"lf\"`)"
5762
},
5863
"experimentalSortImports": {
5964
"description": "Experimental: Sort import statements. Disabled by default.",
@@ -64,7 +69,8 @@ expression: json
6469
{
6570
"type": "null"
6671
}
67-
]
72+
],
73+
"markdownDescription": "Experimental: Sort import statements. Disabled by default."
6874
},
6975
"ignorePatterns": {
7076
"description": "Ignore files matching these glob patterns. Current working directory is used as the root.",
@@ -74,14 +80,16 @@ expression: json
7480
],
7581
"items": {
7682
"type": "string"
77-
}
83+
},
84+
"markdownDescription": "Ignore files matching these glob patterns. Current working directory is used as the root."
7885
},
7986
"jsxSingleQuote": {
8087
"description": "Use single quotes instead of double quotes in JSX. (Default: `false`)",
8188
"type": [
8289
"boolean",
8390
"null"
84-
]
91+
],
92+
"markdownDescription": "Use single quotes instead of double quotes in JSX. (Default: `false`)"
8593
},
8694
"objectWrap": {
8795
"description": "How to wrap object literals when they could fit on one line or span multiple lines. (Default: `\"preserve\"`)\nNOTE: In addition to Prettier's `\"preserve\"` and `\"collapse\"`, we also support `\"always\"`.",
@@ -92,7 +100,8 @@ expression: json
92100
{
93101
"type": "null"
94102
}
95-
]
103+
],
104+
"markdownDescription": "How to wrap object literals when they could fit on one line or span multiple lines. (Default: `\"preserve\"`)\nNOTE: In addition to Prettier's `\"preserve\"` and `\"collapse\"`, we also support `\"always\"`."
96105
},
97106
"printWidth": {
98107
"description": "The line length that the printer will wrap on. (Default: `100`)",
@@ -101,7 +110,8 @@ expression: json
101110
"null"
102111
],
103112
"format": "uint16",
104-
"minimum": 0.0
113+
"minimum": 0.0,
114+
"markdownDescription": "The line length that the printer will wrap on. (Default: `100`)"
105115
},
106116
"quoteProps": {
107117
"description": "Change when properties in objects are quoted. (Default: `\"as-needed\"`)",
@@ -112,28 +122,32 @@ expression: json
112122
{
113123
"type": "null"
114124
}
115-
]
125+
],
126+
"markdownDescription": "Change when properties in objects are quoted. (Default: `\"as-needed\"`)"
116127
},
117128
"semi": {
118129
"description": "Print semicolons at the ends of statements. (Default: `true`)",
119130
"type": [
120131
"boolean",
121132
"null"
122-
]
133+
],
134+
"markdownDescription": "Print semicolons at the ends of statements. (Default: `true`)"
123135
},
124136
"singleAttributePerLine": {
125137
"description": "Put each attribute on a new line in JSX. (Default: `false`)",
126138
"type": [
127139
"boolean",
128140
"null"
129-
]
141+
],
142+
"markdownDescription": "Put each attribute on a new line in JSX. (Default: `false`)"
130143
},
131144
"singleQuote": {
132145
"description": "Use single quotes instead of double quotes. (Default: `false`)",
133146
"type": [
134147
"boolean",
135148
"null"
136-
]
149+
],
150+
"markdownDescription": "Use single quotes instead of double quotes. (Default: `false`)"
137151
},
138152
"tabWidth": {
139153
"description": "Number of spaces per indentation level. (Default: `2`)",
@@ -142,7 +156,8 @@ expression: json
142156
"null"
143157
],
144158
"format": "uint8",
145-
"minimum": 0.0
159+
"minimum": 0.0,
160+
"markdownDescription": "Number of spaces per indentation level. (Default: `2`)"
146161
},
147162
"trailingComma": {
148163
"description": "Print trailing commas wherever possible. (Default: `\"all\"`)",
@@ -153,14 +168,16 @@ expression: json
153168
{
154169
"type": "null"
155170
}
156-
]
171+
],
172+
"markdownDescription": "Print trailing commas wherever possible. (Default: `\"all\"`)"
157173
},
158174
"useTabs": {
159175
"description": "Use tabs for indentation or spaces. (Default: `false`)",
160176
"type": [
161177
"boolean",
162178
"null"
163-
]
179+
],
180+
"markdownDescription": "Use tabs for indentation or spaces. (Default: `false`)"
164181
}
165182
},
166183
"allowComments": true,
@@ -217,7 +234,8 @@ expression: json
217234
"items": {
218235
"type": "string"
219236
}
220-
}
237+
},
238+
"markdownDescription": "Custom groups configuration for organizing imports.\nEach array element represents a group, and multiple group names in the same array are treated as one.\nAccepts both `string` and `string[]` as group elements."
221239
},
222240
"ignoreCase": {
223241
"default": true,
@@ -275,5 +293,6 @@ expression: json
275293
"none"
276294
]
277295
}
278-
}
296+
},
297+
"markdownDescription": "Configuration options for the formatter.\nMost options are the same as Prettier's options.\nSee also <https://prettier.io/docs/options>"
279298
}

0 commit comments

Comments
 (0)