Skip to content

Commit 995de57

Browse files
committed
Add seamless support for using JSON5 in the config file (#47)
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
1 parent 61851f4 commit 995de57

File tree

15 files changed

+321
-73
lines changed

15 files changed

+321
-73
lines changed

.changes/json5.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
"tauri": patch
3+
"tauri-build": patch
4+
"tauri-codegen": patch
5+
"tauri-macros": patch
6+
"tauri-utils": patch
7+
"cli.rs": patch
8+
---
9+
10+
Adds support for using JSON5 format for the `tauri.conf.json` file, along with also supporting the `.json5` extension.
11+
12+
Here is the logic flow that determines if JSON or JSON5 will be used to parse the config:
13+
14+
1. Check if `tauri.conf.json` exists
15+
a. Parse it with `serde_json`
16+
b. Parse it with `json5` if `serde_json` fails
17+
c. Return original `serde_json` error if all above steps failed
18+
2. Check if `tauri.conf.json5` exists
19+
a. Parse it with `json5`
20+
b. Return error if all above steps failed
21+
3. Return error if all above steps failed

core/tauri-build/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ rustdoc-args = [ "--cfg", "doc_cfg" ]
2020
anyhow = "1"
2121
quote = { version = "1", optional = true }
2222
tauri-codegen = { version = "1.0.0-beta.4", path = "../tauri-codegen", optional = true }
23-
serde_json = "1.0"
2423
tauri-utils = { version = "1.0.0-beta.0", path = "../tauri-utils", features = [ "build" ] }
2524
cargo_toml = "0.10"
25+
serde_json = "1"
2626

2727
[target."cfg(windows)".dependencies]
2828
winres = "0.1"
2929

3030
[features]
3131
codegen = [ "tauri-codegen", "quote" ]
3232
isolation = ["tauri-codegen/isolation", "tauri-utils/isolation"]
33+
config-json5 = [ "tauri-utils/config-json5" ]

core/tauri-build/src/codegen/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ impl CodegenContext {
120120
)
121121
})?;
122122

123-
writeln!(&mut file, "{}", code).with_context(|| {
123+
writeln!(file, "{}", code).with_context(|| {
124124
format!(
125125
"Unable to write tokenstream to out file during tauri-build {}",
126126
out.display()

core/tauri-build/src/lib.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,20 @@ pub fn build() {
109109
pub fn try_build(attributes: Attributes) -> Result<()> {
110110
use anyhow::anyhow;
111111
use cargo_toml::{Dependency, Manifest};
112-
use std::fs::read_to_string;
113112
use tauri_utils::config::Config;
114113

115-
println!("cargo:rerun-if-changed=tauri.conf.json");
116114
println!("cargo:rerun-if-changed=src/Cargo.toml");
117-
118-
let config: Config = serde_json::from_str(&read_to_string("tauri.conf.json")?)?;
115+
println!("cargo:rerun-if-changed=tauri.conf.json");
116+
#[cfg(feature = "config-json5")]
117+
println!("cargo:rerun-if-changed=tauri.conf.json5");
118+
119+
let config: Config = if let Ok(env) = std::env::var("TAURI_CONFIG") {
120+
serde_json::from_str(&env)?
121+
} else {
122+
serde_json::from_value(tauri_utils::config::parse::read_from(
123+
std::env::current_dir().unwrap(),
124+
)?)?
125+
};
119126

120127
let mut manifest = Manifest::from_path("Cargo.toml")?;
121128
if let Some(tauri) = manifest.dependencies.remove("tauri") {

core/tauri-codegen/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ default = [ "compression" ]
3232
compression = [ "zstd", "tauri-utils/compression" ]
3333
isolation = ["tauri-utils/isolation"]
3434
shell-scope = []
35+
config-json5 = [ "tauri-utils/config-json5" ]

core/tauri-codegen/src/lib.rs

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,53 +2,41 @@
22
// SPDX-License-Identifier: Apache-2.0
33
// SPDX-License-Identifier: MIT
44

5-
pub use context::{context_codegen, ContextData};
5+
pub use self::context::{context_codegen, ContextData};
66
use std::{
77
borrow::Cow,
8-
fs::File,
9-
io::BufReader,
108
path::{Path, PathBuf},
119
};
12-
use tauri_utils::config::Config;
13-
use thiserror::Error;
10+
pub use tauri_utils::config::{parse::ConfigError, Config};
1411

1512
mod context;
1613
pub mod embedded_assets;
1714

18-
/// Represents all the errors that can happen while reading the config.
19-
#[derive(Debug, Error)]
15+
/// Represents all the errors that can happen while reading the config during codegen.
16+
#[derive(Debug, thiserror::Error)]
2017
#[non_exhaustive]
21-
pub enum ConfigError {
18+
pub enum CodegenConfigError {
2219
#[error("unable to access current working directory: {0}")]
2320
CurrentDir(std::io::Error),
2421

2522
// this error should be "impossible" because we use std::env::current_dir() - cover it anyways
2623
#[error("Tauri config file has no parent, this shouldn't be possible. file an issue on https://github.com/tauri-apps/tauri - target {0}")]
2724
Parent(PathBuf),
2825

29-
#[error("unable to parse inline TAURI_CONFIG env var: {0}")]
26+
#[error("unable to parse inline JSON TAURI_CONFIG env var: {0}")]
3027
FormatInline(serde_json::Error),
3128

32-
#[error("unable to parse Tauri config file at {path} because {error}")]
33-
Format {
34-
path: PathBuf,
35-
error: serde_json::Error,
36-
},
37-
38-
#[error("unable to read Tauri config file at {path} because {error}")]
39-
Io {
40-
path: PathBuf,
41-
error: std::io::Error,
42-
},
29+
#[error("{0}")]
30+
ConfigError(#[from] ConfigError),
4331
}
4432

4533
/// Get the [`Config`] from the `TAURI_CONFIG` environmental variable, or read from the passed path.
4634
///
4735
/// If the passed path is relative, it should be relative to the current working directory of the
4836
/// compiling crate.
49-
pub fn get_config(path: &Path) -> Result<(Config, PathBuf), ConfigError> {
37+
pub fn get_config(path: &Path) -> Result<(Config, PathBuf), CodegenConfigError> {
5038
let path = if path.is_relative() {
51-
let cwd = std::env::current_dir().map_err(ConfigError::CurrentDir)?;
39+
let cwd = std::env::current_dir().map_err(CodegenConfigError::CurrentDir)?;
5240
Cow::Owned(cwd.join(path))
5341
} else {
5442
Cow::Borrowed(path)
@@ -59,27 +47,16 @@ pub fn get_config(path: &Path) -> Result<(Config, PathBuf), ConfigError> {
5947
// already unlikely unless the developer goes out of their way to run the cli on a different
6048
// project than the target crate.
6149
let config = if let Ok(env) = std::env::var("TAURI_CONFIG") {
62-
serde_json::from_str(&env).map_err(ConfigError::FormatInline)?
50+
serde_json::from_str(&env).map_err(CodegenConfigError::FormatInline)?
6351
} else {
64-
File::open(&path)
65-
.map_err(|error| ConfigError::Io {
66-
path: path.clone().into_owned(),
67-
error,
68-
})
69-
.map(BufReader::new)
70-
.and_then(|file| {
71-
serde_json::from_reader(file).map_err(|error| ConfigError::Format {
72-
path: path.clone().into_owned(),
73-
error,
74-
})
75-
})?
52+
tauri_utils::config::parse(path.to_path_buf())?
7653
};
7754

7855
// this should be impossible because of the use of `current_dir()` above, but handle it anyways
7956
let parent = path
8057
.parent()
8158
.map(ToOwned::to_owned)
82-
.ok_or_else(|| ConfigError::Parent(path.into_owned()))?;
59+
.ok_or_else(|| CodegenConfigError::Parent(path.into_owned()))?;
8360

8461
Ok((config, parent))
8562
}

core/tauri-macros/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ quote = "1"
2121
syn = { version = "1", features = [ "full" ] }
2222
heck = "0.3"
2323
tauri-codegen = { version = "1.0.0-beta.4", default-features = false, path = "../tauri-codegen" }
24+
tauri-utils = { version = "1.0.0-beta.3", path = "../tauri-utils" }
2425

2526
[features]
2627
custom-protocol = [ ]
2728
compression = [ "tauri-codegen/compression" ]
2829
isolation = ["tauri-codegen/isolation"]
2930
shell-scope = ["tauri-codegen/shell-scope"]
31+
config-json5 = [ "tauri-codegen/config-json5", "tauri-utils/config-json5" ]

core/tauri-macros/src/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use syn::{
1111
LitStr, PathArguments, PathSegment, Token,
1212
};
1313
use tauri_codegen::{context_codegen, get_config, ContextData};
14+
use tauri_utils::config::parse::does_supported_extension_exist;
1415

1516
pub(crate) struct ContextItems {
1617
config_file: PathBuf,
@@ -35,7 +36,7 @@ impl Parse for ContextItems {
3536
VarError::NotUnicode(_) => "CARGO_MANIFEST_DIR env var contained invalid utf8".into(),
3637
})
3738
.and_then(|path| {
38-
if path.exists() {
39+
if does_supported_extension_exist(&path) {
3940
Ok(path)
4041
} else {
4142
Err(format!(

core/tauri-utils/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ ring = { version = "0.16", optional = true, features = ["std"] }
3131
once_cell = { version = "1.8", optional = true }
3232
serialize-to-javascript = { git = "https://github.com/chippers/serialize-to-javascript" }
3333
ctor = "0.1"
34+
json5 = { version = "0.4", optional = true }
35+
json-patch = "0.2"
3436

3537
[target."cfg(target_os = \"linux\")".dependencies]
3638
heck = "0.4"
@@ -41,3 +43,4 @@ compression = [ "zstd" ]
4143
schema = ["schemars"]
4244
isolation = [ "aes-gcm", "ring", "once_cell" ]
4345
process-relaunch-dangerous-allow-symlink-macos = []
46+
config-json5 = [ "json5" ]

core/tauri-utils/src/config.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ use url::Url;
2424

2525
use std::{collections::HashMap, fmt, fs::read_to_string, path::PathBuf};
2626

27+
/// Items to help with parsing content into a [`Config`].
28+
pub mod parse;
29+
30+
pub use self::parse::parse;
31+
2732
/// The window webview URL options.
2833
#[derive(PartialEq, Debug, Clone, Deserialize, Serialize)]
2934
#[cfg_attr(feature = "schema", derive(JsonSchema))]

0 commit comments

Comments
 (0)