docs: improve resources docs (#14136)

* docs: improve resources docs

* Clippy
This commit is contained in:
Tony
2025-09-01 23:15:43 +08:00
committed by GitHub
parent 5239d39149
commit 346a420812
5 changed files with 158 additions and 90 deletions

View File

@@ -495,7 +495,7 @@
]
},
"incognito": {
"description": "Whether or not the webview should be launched in incognito mode.\n\n ## Platform-specific:\n\n - **Android**: Unsupported.",
"description": "Whether or not the webview should be launched in incognito mode.\n\n ## Platform-specific:\n\n - **Android**: Unsupported.",
"default": false,
"type": "boolean"
},
@@ -2071,7 +2071,7 @@
}
},
"resources": {
"description": "App resources to bundle.\n Each resource is a path to a file or directory.\n Glob patterns are supported.",
"description": "App resources to bundle.\n Each resource is a path to a file or directory.\n Glob patterns are supported.\n\n ## Examples\n\n To include a list of files:\n\n ```json\n {\n \"bundle\": {\n \"resources\": [\n \"./path/to/some-file.txt\",\n \"/absolute/path/to/textfile.txt\",\n \"../relative/path/to/jsonfile.json\",\n \"some-folder/\",\n \"resources/**/*.md\"\n ]\n }\n }\n ```\n\n The bundled files will be in `$RESOURCES/` with the original directory structure preserved,\n for example: `./path/to/some-file.txt` -> `$RESOURCE/path/to/some-file.txt`\n\n To fine control where the files will get copied to, use a map instead\n\n ```json\n {\n \"bundle\": {\n \"resources\": {\n \"/absolute/path/to/textfile.txt\": \"resources/textfile.txt\",\n \"relative/path/to/jsonfile.json\": \"resources/jsonfile.json\",\n \"resources/\": \"\",\n \"docs/**/*md\": \"website-docs/\"\n }\n }\n }\n ```\n\n Note that when using glob pattern in this case, the original directory structure is not preserved,\n everything gets copied to the target directory directly\n\n See more: <https://v2.tauri.app/develop/resources/>",
"anyOf": [
{
"$ref": "#/definitions/BundleResources"
@@ -2921,7 +2921,7 @@
]
},
"installerHooks": {
"description": "A path to a `.nsh` file that contains special NSIS macros to be hooked into the\n main installer.nsi script.\n\n Supported hooks are:\n - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.\n - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.\n - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.\n - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.\n\n\n ### Example\n\n ```nsh\n !macro NSIS_HOOK_PREINSTALL\n MessageBox MB_OK \"PreInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTINSTALL\n MessageBox MB_OK \"PostInstall\"\n !macroend\n\n !macro NSIS_HOOK_PREUNINSTALL\n MessageBox MB_OK \"PreUnInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTUNINSTALL\n MessageBox MB_OK \"PostUninstall\"\n !macroend\n\n ```",
"description": "A path to a `.nsh` file that contains special NSIS macros to be hooked into the\n main installer.nsi script.\n\n Supported hooks are:\n\n - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.\n - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.\n - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.\n - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.\n\n ### Example\n\n ```nsh\n !macro NSIS_HOOK_PREINSTALL\n MessageBox MB_OK \"PreInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTINSTALL\n MessageBox MB_OK \"PostInstall\"\n !macroend\n\n !macro NSIS_HOOK_PREUNINSTALL\n MessageBox MB_OK \"PreUnInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTUNINSTALL\n MessageBox MB_OK \"PostUninstall\"\n !macroend\n ```",
"type": [
"string",
"null"

View File

@@ -495,7 +495,7 @@
]
},
"incognito": {
"description": "Whether or not the webview should be launched in incognito mode.\n\n ## Platform-specific:\n\n - **Android**: Unsupported.",
"description": "Whether or not the webview should be launched in incognito mode.\n\n ## Platform-specific:\n\n - **Android**: Unsupported.",
"default": false,
"type": "boolean"
},
@@ -2071,7 +2071,7 @@
}
},
"resources": {
"description": "App resources to bundle.\n Each resource is a path to a file or directory.\n Glob patterns are supported.",
"description": "App resources to bundle.\n Each resource is a path to a file or directory.\n Glob patterns are supported.\n\n ## Examples\n\n To include a list of files:\n\n ```json\n {\n \"bundle\": {\n \"resources\": [\n \"./path/to/some-file.txt\",\n \"/absolute/path/to/textfile.txt\",\n \"../relative/path/to/jsonfile.json\",\n \"some-folder/\",\n \"resources/**/*.md\"\n ]\n }\n }\n ```\n\n The bundled files will be in `$RESOURCES/` with the original directory structure preserved,\n for example: `./path/to/some-file.txt` -> `$RESOURCE/path/to/some-file.txt`\n\n To fine control where the files will get copied to, use a map instead\n\n ```json\n {\n \"bundle\": {\n \"resources\": {\n \"/absolute/path/to/textfile.txt\": \"resources/textfile.txt\",\n \"relative/path/to/jsonfile.json\": \"resources/jsonfile.json\",\n \"resources/\": \"\",\n \"docs/**/*md\": \"website-docs/\"\n }\n }\n }\n ```\n\n Note that when using glob pattern in this case, the original directory structure is not preserved,\n everything gets copied to the target directory directly\n\n See more: <https://v2.tauri.app/develop/resources/>",
"anyOf": [
{
"$ref": "#/definitions/BundleResources"
@@ -2921,7 +2921,7 @@
]
},
"installerHooks": {
"description": "A path to a `.nsh` file that contains special NSIS macros to be hooked into the\n main installer.nsi script.\n\n Supported hooks are:\n - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.\n - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.\n - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.\n - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.\n\n\n ### Example\n\n ```nsh\n !macro NSIS_HOOK_PREINSTALL\n MessageBox MB_OK \"PreInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTINSTALL\n MessageBox MB_OK \"PostInstall\"\n !macroend\n\n !macro NSIS_HOOK_PREUNINSTALL\n MessageBox MB_OK \"PreUnInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTUNINSTALL\n MessageBox MB_OK \"PostUninstall\"\n !macroend\n\n ```",
"description": "A path to a `.nsh` file that contains special NSIS macros to be hooked into the\n main installer.nsi script.\n\n Supported hooks are:\n\n - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.\n - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.\n - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.\n - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.\n\n ### Example\n\n ```nsh\n !macro NSIS_HOOK_PREINSTALL\n MessageBox MB_OK \"PreInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTINSTALL\n MessageBox MB_OK \"PostInstall\"\n !macroend\n\n !macro NSIS_HOOK_PREUNINSTALL\n MessageBox MB_OK \"PreUnInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTUNINSTALL\n MessageBox MB_OK \"PostUninstall\"\n !macroend\n ```",
"type": [
"string",
"null"

View File

@@ -908,12 +908,12 @@ pub struct NsisConfig {
/// main installer.nsi script.
///
/// Supported hooks are:
///
/// - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.
/// - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.
/// - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.
/// - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.
///
///
/// ### Example
///
/// ```nsh
@@ -932,7 +932,6 @@ pub struct NsisConfig {
/// !macro NSIS_HOOK_POSTUNINSTALL
/// MessageBox MB_OK "PostUninstall"
/// !macroend
///
/// ```
#[serde(alias = "installer-hooks")]
pub installer_hooks: Option<PathBuf>,
@@ -1286,6 +1285,47 @@ pub struct BundleConfig {
/// App resources to bundle.
/// Each resource is a path to a file or directory.
/// Glob patterns are supported.
///
/// ## Examples
///
/// To include a list of files:
///
/// ```json
/// {
/// "bundle": {
/// "resources": [
/// "./path/to/some-file.txt",
/// "/absolute/path/to/textfile.txt",
/// "../relative/path/to/jsonfile.json",
/// "some-folder/",
/// "resources/**/*.md"
/// ]
/// }
/// }
/// ```
///
/// The bundled files will be in `$RESOURCES/` with the original directory structure preserved,
/// for example: `./path/to/some-file.txt` -> `$RESOURCE/path/to/some-file.txt`
///
/// To fine control where the files will get copied to, use a map instead
///
/// ```json
/// {
/// "bundle": {
/// "resources": {
/// "/absolute/path/to/textfile.txt": "resources/textfile.txt",
/// "relative/path/to/jsonfile.json": "resources/jsonfile.json",
/// "resources/": "",
/// "docs/**/*md": "website-docs/"
/// }
/// }
/// }
/// ```
///
/// Note that when using glob pattern in this case, the original directory structure is not preserved,
/// everything gets copied to the target directory directly
///
/// See more: <https://v2.tauri.app/develop/resources/>
pub resources: Option<BundleResources>,
/// A copyright string associated with your application.
pub copyright: Option<String>,
@@ -1743,9 +1783,9 @@ pub struct WindowConfig {
pub window_effects: Option<WindowEffectsConfig>,
/// Whether or not the webview should be launched in incognito mode.
///
/// ## Platform-specific:
/// ## Platform-specific:
///
/// - **Android**: Unsupported.
/// - **Android**: Unsupported.
#[serde(default)]
pub incognito: bool,
/// Sets the window associated with this label to be the parent of the window to be created.

View File

@@ -137,7 +137,11 @@ pub struct ResourcePathsIter<'a> {
allow_walk: bool,
current_path: Option<PathBuf>,
/// The key of map when `pattern_iter` is a [`PatternIter::Map`],
/// used for determining [`Resource::target`]
current_pattern: Option<String>,
/// The value of the map when `pattern_iter` is a [`PatternIter::Map`],
/// used for determining [`Resource::target`]
current_dest: Option<PathBuf>,
walk_iter: Option<walkdir::IntoIter>,
@@ -176,28 +180,27 @@ impl ResourcePathsIter<'_> {
Ok(Resource {
path: path.to_path_buf(),
target: self
.current_dest
.as_ref()
.map(|current_dest| {
// if processing a directory, preserve directory structure under current_dest
if self.walk_iter.is_some() {
let current_pattern = self.current_pattern.as_ref().unwrap();
current_dest.join(path.strip_prefix(current_pattern).unwrap_or(path))
} else if current_dest.components().count() == 0 {
// if current_dest is empty while processing a file pattern or glob
// we preserve the file name as it is
PathBuf::from(path.file_name().unwrap())
} else if self.glob_iter.is_some() {
// if processing a glob and current_dest is not empty
// we put all globbed paths under current_dest
// preserving the file name as it is
current_dest.join(path.file_name().unwrap())
} else {
current_dest.clone()
}
})
.unwrap_or_else(|| resource_relpath(path)),
target: if let Some(current_dest) = &self.current_dest {
// if processing a directory, preserve directory structure under current_dest
if self.walk_iter.is_some() {
let current_pattern = self.current_pattern.as_ref().unwrap();
current_dest.join(path.strip_prefix(current_pattern).unwrap_or(path))
} else if current_dest.components().count() == 0 {
// if current_dest is empty while processing a file pattern or glob
// we preserve the file name as it is
PathBuf::from(path.file_name().unwrap())
} else if self.glob_iter.is_some() {
// if processing a glob and current_dest is not empty
// we put all globbed paths under current_dest
// preserving the file name as it is
current_dest.join(path.file_name().unwrap())
} else {
current_dest.clone()
}
} else {
// If `pattern_iter` is a [`PatternIter::Slice`]
resource_relpath(path)
},
})
}
@@ -240,14 +243,12 @@ impl ResourcePathsIter<'_> {
let pattern = match &mut self.pattern_iter {
PatternIter::Slice(iter) => iter.next()?,
PatternIter::Map(iter) => match iter.next() {
Some((pattern, dest)) => {
self.current_pattern = Some(pattern.clone());
self.current_dest = Some(resource_relpath(Path::new(dest)));
pattern
}
None => return None,
},
PatternIter::Map(iter) => {
let (pattern, dest) = iter.next()?;
self.current_pattern = Some(pattern.clone());
self.current_dest = Some(resource_relpath(Path::new(dest)));
pattern
}
};
if pattern.contains('*') {
@@ -339,39 +340,47 @@ mod tests {
std::env::set_current_dir(&temp).unwrap();
let paths = [
Path::new("src-tauri/tauri.conf.json"),
Path::new("src-tauri/some-other-json.json"),
Path::new("src-tauri/Cargo.toml"),
Path::new("src-tauri/Tauri.toml"),
Path::new("src-tauri/build.rs"),
Path::new("src/assets/javascript.svg"),
Path::new("src/assets/tauri.svg"),
Path::new("src/assets/rust.svg"),
Path::new("src/assets/lang/en.json"),
Path::new("src/assets/lang/ar.json"),
Path::new("src/sounds/lang/es.wav"),
Path::new("src/sounds/lang/fr.wav"),
Path::new("src/textures/ground/earth.tex"),
Path::new("src/textures/ground/sand.tex"),
Path::new("src/textures/water.tex"),
Path::new("src/textures/fire.tex"),
Path::new("src/tiles/sky/grey.tile"),
Path::new("src/tiles/sky/yellow.tile"),
Path::new("src/tiles/grass.tile"),
Path::new("src/tiles/stones.tile"),
Path::new("src/index.html"),
Path::new("src/style.css"),
Path::new("src/script.js"),
Path::new("src/dir/another-dir/file1.txt"),
Path::new("src/dir/another-dir2/file2.txt"),
"src-tauri/tauri.conf.json",
"src-tauri/some-other-json.json",
"src-tauri/Cargo.toml",
"src-tauri/Tauri.toml",
"src-tauri/build.rs",
"src/assets/javascript.svg",
"src/assets/tauri.svg",
"src/assets/rust.svg",
"src/assets/lang/en.json",
"src/assets/lang/ar.json",
"src/sounds/lang/es.wav",
"src/sounds/lang/fr.wav",
"src/textures/ground/earth.tex",
"src/textures/ground/sand.tex",
"src/textures/water.tex",
"src/textures/fire.tex",
"src/tiles/sky/grey.tile",
"src/tiles/sky/yellow.tile",
"src/tiles/grass.tile",
"src/tiles/stones.tile",
"src/index.html",
"src/style.css",
"src/script.js",
"src/dir/another-dir/file1.txt",
"src/dir/another-dir2/file2.txt",
];
for path in paths {
let path = Path::new(path);
fs::create_dir_all(path.parent().unwrap()).unwrap();
fs::write(path, "").unwrap();
}
}
fn resources_map(literal: &[(&str, &str)]) -> HashMap<String, String> {
literal
.iter()
.map(|(from, to)| (from.to_string(), to.to_string()))
.collect()
}
#[test]
#[serial_test::serial(resources)]
fn resource_paths_iter_slice_allow_walk() {
@@ -386,6 +395,8 @@ mod tests {
"../src/assets".into(),
"../src/index.html".into(),
"../src/sounds".into(),
// Should be the same as `../src/textures/` or `../src/textures`
"../src/textures/**/*".into(),
"*.toml".into(),
"*.conf.json".into(),
],
@@ -396,7 +407,9 @@ mod tests {
.collect::<Vec<_>>();
let expected = expected_resources(&[
// From `../src/script.js`
("../src/script.js", "_up_/src/script.js"),
// From `../src/assets`
(
"../src/assets/javascript.svg",
"_up_/src/assets/javascript.svg",
@@ -405,11 +418,26 @@ mod tests {
("../src/assets/rust.svg", "_up_/src/assets/rust.svg"),
("../src/assets/lang/en.json", "_up_/src/assets/lang/en.json"),
("../src/assets/lang/ar.json", "_up_/src/assets/lang/ar.json"),
// From `../src/index.html`
("../src/index.html", "_up_/src/index.html"),
// From `../src/sounds`
("../src/sounds/lang/es.wav", "_up_/src/sounds/lang/es.wav"),
("../src/sounds/lang/fr.wav", "_up_/src/sounds/lang/fr.wav"),
// From `../src/textures/**/*`
(
"../src/textures/ground/earth.tex",
"_up_/src/textures/earth.tex",
),
(
"../src/textures/ground/sand.tex",
"_up_/src/textures/sand.tex",
),
("../src/textures/water.tex", "_up_/src/textures/water.tex"),
("../src/textures/fire.tex", "_up_/src/textures/fire.tex"),
// From `*.toml`
("Cargo.toml", "Cargo.toml"),
("Tauri.toml", "Tauri.toml"),
// From `*.conf.json`
("tauri.conf.json", "tauri.conf.json"),
]);
@@ -469,17 +497,17 @@ mod tests {
let _ = std::env::set_current_dir(dir);
let resources = ResourcePaths::from_map(
&std::collections::HashMap::from_iter([
("../src/script.js".into(), "main.js".into()),
("../src/assets".into(), "".into()),
("../src/index.html".into(), "frontend/index.html".into()),
("../src/sounds".into(), "voices".into()),
("../src/textures/*".into(), "textures".into()),
("../src/tiles/**/*".into(), "tiles".into()),
("*.toml".into(), "".into()),
("*.conf.json".into(), "json".into()),
("../non-existent-file".into(), "asd".into()), // invalid case
("../non/*".into(), "asd".into()), // invalid case
&resources_map(&[
("../src/script.js", "main.js"),
("../src/assets", ""),
("../src/index.html", "frontend/index.html"),
("../src/sounds", "voices"),
("../src/textures/*", "textures"),
("../src/tiles/**/*", "tiles"),
("*.toml", ""),
("*.conf.json", "json"),
("../non-existent-file", "asd"), // invalid case
("../non/*", "asd"), // invalid case
]),
true,
)
@@ -525,13 +553,13 @@ mod tests {
let _ = std::env::set_current_dir(dir);
let resources = ResourcePaths::from_map(
&std::collections::HashMap::from_iter([
("../src/script.js".into(), "main.js".into()),
("../src/assets".into(), "".into()),
("../src/index.html".into(), "frontend/index.html".into()),
("../src/sounds".into(), "voices".into()),
("*.toml".into(), "".into()),
("*.conf.json".into(), "json".into()),
&resources_map(&[
("../src/script.js", "main.js"),
("../src/assets", ""),
("../src/index.html", "frontend/index.html"),
("../src/sounds", "voices"),
("*.toml", ""),
("*.conf.json", "json"),
]),
false,
)
@@ -564,15 +592,15 @@ mod tests {
let _ = std::env::set_current_dir(dir);
let resources = ResourcePaths::from_map(
&std::collections::HashMap::from_iter([
("../non-existent-file".into(), "file".into()),
("../non-existent-dir".into(), "dir".into()),
&resources_map(&[
("../non-existent-file", "file"),
("../non-existent-dir", "dir"),
// exists but not allowed to walk
("../src".into(), "dir2".into()),
("../src", "dir2"),
// doesn't exist but it is a glob and will return an error
("../non-existent-glob-dir/*".into(), "glob".into()),
("../non-existent-glob-dir/*", "glob"),
// exists but only contains directories and will not produce any values
("../src/dir/*".into(), "dir3".into()),
("../src/dir/*", "dir3"),
]),
false,
)

View File

@@ -124,7 +124,7 @@ pub enum BaseDirectory {
/// Resolves to [`crate::path::PathResolver::video_dir`].
Video = 10,
/// The Resource directory.
/// Resolves to the resource directory of this app.
/// Resolves to [`crate::path::PathResolver::resource_dir`].
Resource = 11,
/// A temporary directory.
/// Resolves to [`std::env::temp_dir`].