Skip to content

Commit 2b7e145

Browse files
authored
feat(fmt): support formatting code blocks in Jupyter notebooks (#21310)
1 parent 3d47c7e commit 2b7e145

File tree

10 files changed

+272
-26
lines changed

10 files changed

+272
-26
lines changed

.dprint.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"cli/tests/testdata/file_extensions/ts_with_js_extension.js",
3131
"cli/tests/testdata/fmt/badly_formatted.json",
3232
"cli/tests/testdata/fmt/badly_formatted.md",
33+
"cli/tests/testdata/fmt/badly_formatted.ipynb",
3334
"cli/tests/testdata/byte_order_mark.ts",
3435
"cli/tests/testdata/encoding",
3536
"cli/tests/testdata/fmt/",

Cargo.lock

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

cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ dotenvy = "0.15.7"
8484
dprint-plugin-json = "=0.19.1"
8585
dprint-plugin-markdown = "=0.16.3"
8686
dprint-plugin-typescript = "=0.88.5"
87+
dprint-plugin-jupyter = "=0.1.1"
8788
encoding_rs.workspace = true
8889
env_logger = "=0.10.0"
8990
fancy-regex = "=0.10.0"

cli/args/flags.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1579,7 +1579,9 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
15791579
.help("Set content type of the supplied file")
15801580
// prefer using ts for formatting instead of js because ts works in more scenarios
15811581
.default_value("ts")
1582-
.value_parser(["ts", "tsx", "js", "jsx", "md", "json", "jsonc"]),
1582+
.value_parser([
1583+
"ts", "tsx", "js", "jsx", "md", "json", "jsonc", "ipynb",
1584+
]),
15831585
)
15841586
.arg(
15851587
Arg::new("ignore")

cli/build.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,11 +359,7 @@ fn create_cli_snapshot(snapshot_path: PathBuf) -> CreateSnapshotOutput {
359359
// Ideally we could deduplicate that code.
360360
fn deno_version() -> String {
361361
if env::var("DENO_CANARY").is_ok() {
362-
format!(
363-
"{}+{}",
364-
env!("CARGO_PKG_VERSION"),
365-
git_commit_hash()[..7].to_string()
366-
)
362+
format!("{}+{}", env!("CARGO_PKG_VERSION"), &git_commit_hash()[..7])
367363
} else {
368364
env!("CARGO_PKG_VERSION").to_string()
369365
}

cli/tests/integration/fmt_tests.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,24 @@ fn fmt_test() {
2727
testdata_fmt_dir.join("badly_formatted.json");
2828
let badly_formatted_json = t.path().join("badly_formatted.json");
2929
badly_formatted_original_json.copy(&badly_formatted_json);
30-
// First, check formatting by ignoring the badly formatted file.
3130

31+
let fixed_ipynb = testdata_fmt_dir.join("badly_formatted_fixed.ipynb");
32+
let badly_formatted_original_ipynb =
33+
testdata_fmt_dir.join("badly_formatted.ipynb");
34+
let badly_formatted_ipynb = t.path().join("badly_formatted.ipynb");
35+
badly_formatted_original_ipynb.copy(&badly_formatted_ipynb);
36+
37+
// First, check formatting by ignoring the badly formatted file.
3238
let output = context
3339
.new_command()
3440
.current_dir(&testdata_fmt_dir)
3541
.args_vec(vec![
3642
"fmt".to_string(),
3743
format!(
38-
"--ignore={badly_formatted_js},{badly_formatted_md},{badly_formatted_json}",
44+
"--ignore={badly_formatted_js},{badly_formatted_md},{badly_formatted_json},{badly_formatted_ipynb}",
3945
),
4046
format!(
41-
"--check {badly_formatted_js} {badly_formatted_md} {badly_formatted_json}",
47+
"--check {badly_formatted_js} {badly_formatted_md} {badly_formatted_json} {badly_formatted_ipynb}",
4248
),
4349
])
4450
.run();
@@ -57,6 +63,7 @@ fn fmt_test() {
5763
badly_formatted_js.to_string(),
5864
badly_formatted_md.to_string(),
5965
badly_formatted_json.to_string(),
66+
badly_formatted_ipynb.to_string(),
6067
])
6168
.run();
6269

@@ -72,6 +79,7 @@ fn fmt_test() {
7279
badly_formatted_js.to_string(),
7380
badly_formatted_md.to_string(),
7481
badly_formatted_json.to_string(),
82+
badly_formatted_ipynb.to_string(),
7583
])
7684
.run();
7785

@@ -81,12 +89,15 @@ fn fmt_test() {
8189
let expected_js = fixed_js.read_to_string();
8290
let expected_md = fixed_md.read_to_string();
8391
let expected_json = fixed_json.read_to_string();
92+
let expected_ipynb = fixed_ipynb.read_to_string();
8493
let actual_js = badly_formatted_js.read_to_string();
8594
let actual_md = badly_formatted_md.read_to_string();
8695
let actual_json = badly_formatted_json.read_to_string();
96+
let actual_ipynb = badly_formatted_ipynb.read_to_string();
8797
assert_eq!(expected_js, actual_js);
8898
assert_eq!(expected_md, actual_md);
8999
assert_eq!(expected_json, actual_json);
100+
assert_eq!(expected_ipynb, actual_ipynb);
90101
}
91102

92103
#[test]
@@ -198,6 +209,12 @@ itest!(fmt_stdin_json {
198209
output_str: Some("{ \"key\": \"value\" }\n"),
199210
});
200211

212+
itest!(fmt_stdin_ipynb {
213+
args: "fmt --ext=ipynb -",
214+
input: Some(include_str!("../testdata/fmt/badly_formatted.ipynb")),
215+
output_str: Some(include_str!("../testdata/fmt/badly_formatted_fixed.ipynb")),
216+
});
217+
201218
itest!(fmt_stdin_check_formatted {
202219
args: "fmt --check -",
203220
input: Some("const a = 1;\n"),
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Hello Markdown\n",
8+
"this isn't formatted properly"
9+
]
10+
},
11+
{
12+
"cell_type": "code",
13+
"execution_count": 5,
14+
"metadata": {},
15+
"outputs": [
16+
{
17+
"name": "stdout",
18+
"output_type": "stream",
19+
"text": [
20+
"Hello World\n"
21+
]
22+
}
23+
],
24+
"source": [
25+
"console.log(\"Hello World\"\n",
26+
"\n",
27+
");"
28+
]
29+
},
30+
{
31+
"cell_type": "raw",
32+
"metadata": {},
33+
"source": [
34+
"raw text\n",
35+
" here too\n"
36+
]
37+
},
38+
{
39+
"cell_type": "code",
40+
"execution_count": 6,
41+
"metadata": {},
42+
"outputs": [
43+
{
44+
"name": "stdout",
45+
"output_type": "stream",
46+
"text": [
47+
"alice\n"
48+
]
49+
}
50+
],
51+
"source": [
52+
"function hello(name: string ) {\n",
53+
" console.log(name);\n",
54+
"};\n",
55+
"\n",
56+
"hello( \"alice\");\n"
57+
]
58+
},
59+
{
60+
"cell_type": "code",
61+
"execution_count": 7,
62+
"metadata": {},
63+
"outputs": [],
64+
"source": [
65+
"function foo(): number {\n",
66+
" return 2;\n",
67+
"}\n"
68+
]
69+
},
70+
{
71+
"cell_type": "code",
72+
"execution_count": 8,
73+
"metadata": {},
74+
"outputs": [
75+
{
76+
"name": "stdout",
77+
"output_type": "stream",
78+
"text": [
79+
"loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\n"
80+
]
81+
}
82+
],
83+
"source": [
84+
"console.log(\"loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\");"
85+
]
86+
}
87+
],
88+
"metadata": {
89+
"kernelspec": {
90+
"display_name": "Deno",
91+
"language": "typescript",
92+
"name": "deno"
93+
},
94+
"language_info": {
95+
"file_extension": ".ts",
96+
"mimetype": "text/x.typescript",
97+
"name": "typescript",
98+
"nb_converter": "script",
99+
"pygments_lexer": "typescript",
100+
"version": "5.2.2"
101+
}
102+
},
103+
"nbformat": 4,
104+
"nbformat_minor": 2
105+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Hello Markdown\n",
8+
"\n",
9+
"this isn't formatted properly"
10+
]
11+
},
12+
{
13+
"cell_type": "code",
14+
"execution_count": 5,
15+
"metadata": {},
16+
"outputs": [
17+
{
18+
"name": "stdout",
19+
"output_type": "stream",
20+
"text": [
21+
"Hello World\n"
22+
]
23+
}
24+
],
25+
"source": [
26+
"console.log(\"Hello World\");"
27+
]
28+
},
29+
{
30+
"cell_type": "raw",
31+
"metadata": {},
32+
"source": [
33+
"raw text\n",
34+
" here too\n"
35+
]
36+
},
37+
{
38+
"cell_type": "code",
39+
"execution_count": 6,
40+
"metadata": {},
41+
"outputs": [
42+
{
43+
"name": "stdout",
44+
"output_type": "stream",
45+
"text": [
46+
"alice\n"
47+
]
48+
}
49+
],
50+
"source": [
51+
"function hello(name: string) {\n",
52+
" console.log(name);\n",
53+
"}\n",
54+
"\n",
55+
"hello(\"alice\");"
56+
]
57+
},
58+
{
59+
"cell_type": "code",
60+
"execution_count": 7,
61+
"metadata": {},
62+
"outputs": [],
63+
"source": [
64+
"function foo(): number {\n",
65+
" return 2;\n",
66+
"}"
67+
]
68+
},
69+
{
70+
"cell_type": "code",
71+
"execution_count": 8,
72+
"metadata": {},
73+
"outputs": [
74+
{
75+
"name": "stdout",
76+
"output_type": "stream",
77+
"text": [
78+
"loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\n"
79+
]
80+
}
81+
],
82+
"source": [
83+
"console.log(\n",
84+
" \"loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\",\n",
85+
");"
86+
]
87+
}
88+
],
89+
"metadata": {
90+
"kernelspec": {
91+
"display_name": "Deno",
92+
"language": "typescript",
93+
"name": "deno"
94+
},
95+
"language_info": {
96+
"file_extension": ".ts",
97+
"mimetype": "text/x.typescript",
98+
"name": "typescript",
99+
"nb_converter": "script",
100+
"pygments_lexer": "typescript",
101+
"version": "5.2.2"
102+
}
103+
},
104+
"nbformat": 4,
105+
"nbformat_minor": 2
106+
}

cli/tests/testdata/fmt/expected_fmt_check_verbose_tests_dir.out

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)