raw
1#![deny(rust_2018_idioms, unsafe_code)]
2#![warn(
3 absolute_paths_not_starting_with_crate,
4 ambiguous_associated_items,
5 anonymous_parameters,
6 arithmetic_overflow,
7 array_into_iter,
8 asm_sub_register,
9 bad_asm_style,
10 bindings_with_variant_name,
11 break_with_label_and_loop,
12 clashing_extern_declarations,
13 coherence_leak_check,
14 conflicting_repr_hints,
15 confusable_idents,
16 const_evaluatable_unchecked,
17 const_item_mutation,
18 dangling_pointers_from_temporaries,
19 dead_code,
20 deprecated_in_future,
21 deprecated_where_clause_location,
22 deprecated,
23 deref_into_dyn_supertrait,
24 deref_nullptr,
25 drop_bounds,
26 duplicate_macro_attributes,
27 dyn_drop,
28 ellipsis_inclusive_range_patterns,
29 enum_intrinsics_non_enums,
30 explicit_outlives_requirements,
31 exported_private_dependencies,
32 forbidden_lint_groups,
33 function_item_references,
34 future_incompatible,
35 ill_formed_attribute_input,
36 improper_ctypes_definitions,
37 improper_ctypes,
38 incomplete_features,
39 incomplete_include,
40 ineffective_unstable_trait_impl,
41 inline_no_sanitize,
42 invalid_atomic_ordering,
43 invalid_doc_attributes,
44 invalid_type_param_default,
45 invalid_value,
46 irrefutable_let_patterns,
47 keyword_idents,
48 large_assignments,
49 late_bound_lifetime_arguments,
50 legacy_derive_helpers,
51 macro_expanded_macro_exports_accessed_by_absolute_paths,
52 meta_variable_misuse,
53 missing_abi,
54 missing_copy_implementations,
55 missing_debug_implementations,
56 missing_docs,
57 mixed_script_confusables,
58 mutable_transmutes,
59 named_arguments_used_positionally,
60 named_asm_labels,
61 no_mangle_const_items,
62 no_mangle_generic_items,
63 non_ascii_idents,
64 non_camel_case_types,
65 non_fmt_panics,
66 non_shorthand_field_patterns,
67 non_snake_case,
68 non_upper_case_globals,
69 nonstandard_style,
70 noop_method_call,
71 overflowing_literals,
72 overlapping_range_endpoints,
73 path_statements,
74 patterns_in_fns_without_body,
75 proc_macro_derive_resolution_fallback,
76 pub_use_of_private_extern_crate,
77 redundant_semicolons,
78 repr_transparent_external_private_fields,
79 rust_2021_incompatible_closure_captures,
80 rust_2021_incompatible_or_patterns,
81 rust_2021_prefixes_incompatible_syntax,
82 rust_2021_prelude_collisions,
83 semicolon_in_expressions_from_macros,
84 soft_unstable,
85 stable_features,
86 text_direction_codepoint_in_comment,
87 text_direction_codepoint_in_literal,
88 trivial_bounds,
89 trivial_casts,
90 trivial_numeric_casts,
91 type_alias_bounds,
92 tyvar_behind_raw_pointer,
93 uncommon_codepoints,
94 unconditional_panic,
95 unconditional_recursion,
96 unexpected_cfgs,
97 uninhabited_static,
98 unknown_crate_types,
99 unnameable_test_items,
100 unreachable_code,
101 unreachable_patterns,
102 unsafe_op_in_unsafe_fn,
103 unstable_features,
104 unstable_name_collisions,
105 unused_allocation,
106 unused_assignments,
107 unused_attributes,
108 unused_braces,
109 unused_comparisons,
110 unused_crate_dependencies,
111 unused_doc_comments,
112 unused_extern_crates,
113 unused_features,
114 unused_import_braces,
115 unused_imports,
116 unused_labels,
117 unused_lifetimes,
118 unused_macro_rules,
119 unused_macros,
120 unused_must_use,
121 unused_mut,
122 unused_parens,
123 unused_qualifications,
124 unused_unsafe,
125 unused_variables,
126 useless_deprecated,
127 while_true
128)]
129#![warn(
130 clippy::all,
131 clippy::await_holding_lock,
132 clippy::char_lit_as_u8,
133 clippy::checked_conversions,
134 clippy::cognitive_complexity,
135 clippy::dbg_macro,
136 clippy::debug_assert_with_mut_call,
137 clippy::disallowed_script_idents,
138 clippy::doc_link_with_quotes,
139 clippy::doc_markdown,
140 clippy::empty_enum,
141 clippy::empty_line_after_outer_attr,
142 clippy::empty_structs_with_brackets,
143 clippy::enum_glob_use,
144 clippy::equatable_if_let,
145 clippy::exit,
146 clippy::expl_impl_clone_on_copy,
147 clippy::explicit_deref_methods,
148 clippy::explicit_into_iter_loop,
149 clippy::fallible_impl_from,
150 clippy::filter_map_next,
151 clippy::flat_map_option,
152 clippy::float_cmp_const,
153 clippy::float_cmp,
154 clippy::float_equality_without_abs,
155 clippy::fn_params_excessive_bools,
156 clippy::fn_to_numeric_cast_any,
157 clippy::from_iter_instead_of_collect,
158 clippy::if_let_mutex,
159 clippy::implicit_clone,
160 clippy::imprecise_flops,
161 clippy::index_refutable_slice,
162 clippy::inefficient_to_string,
163 clippy::invalid_upcast_comparisons,
164 clippy::iter_not_returning_iterator,
165 clippy::large_digit_groups,
166 clippy::large_stack_arrays,
167 clippy::large_types_passed_by_value,
168 clippy::let_unit_value,
169 clippy::linkedlist,
170 clippy::lossy_float_literal,
171 clippy::macro_use_imports,
172 clippy::manual_ok_or,
173 clippy::map_err_ignore,
174 clippy::map_flatten,
175 clippy::map_unwrap_or,
176 clippy::match_same_arms,
177 clippy::match_wild_err_arm,
178 clippy::match_wildcard_for_single_variants,
179 clippy::mem_forget,
180 clippy::missing_const_for_fn,
181 clippy::missing_enforced_import_renames,
182 clippy::missing_errors_doc,
183 clippy::missing_panics_doc,
184 clippy::mut_mut,
185 clippy::mutex_integer,
186 clippy::needless_borrow,
187 clippy::needless_continue,
188 clippy::needless_for_each,
189 clippy::needless_pass_by_value,
190 clippy::negative_feature_names,
191 clippy::nonstandard_macro_braces,
192 clippy::nursery,
193 clippy::option_if_let_else,
194 clippy::option_option,
195 clippy::path_buf_push_overwrite,
196 clippy::pedantic,
197 clippy::print_stderr,
198 clippy::print_stdout,
199 clippy::ptr_as_ptr,
200 clippy::rc_mutex,
201 clippy::ref_option_ref,
202 clippy::rest_pat_in_fully_bound_structs,
203 clippy::same_functions_in_if_condition,
204 clippy::semicolon_if_nothing_returned,
205 clippy::shadow_unrelated,
206 clippy::similar_names,
207 clippy::single_match_else,
208 clippy::string_add_assign,
209 clippy::string_add,
210 clippy::string_lit_as_bytes,
211 clippy::suspicious_operation_groupings,
212 clippy::todo,
213 clippy::trailing_empty_array,
214 clippy::trait_duplication_in_bounds,
215 clippy::trivially_copy_pass_by_ref,
216 clippy::unimplemented,
217 clippy::unnecessary_wraps,
218 clippy::unnested_or_patterns,
219 clippy::unseparated_literal_suffix,
220 clippy::unused_self,
221 clippy::use_debug,
222 clippy::use_self,
223 clippy::used_underscore_binding,
224 clippy::useless_let_if_seq,
225 clippy::useless_transmute,
226 clippy::verbose_file_reads,
227 clippy::wildcard_dependencies,
228 clippy::wildcard_imports,
229 clippy::zero_sized_map_values
230)]
231
232
234mod utils;
235
236#[cfg(feature = "base")]
237mod base;
238#[cfg(feature = "canvas")]
239mod canvas;
240mod data;
241mod file;
242mod link;
243mod note;
244mod vault;
245
246use std::fmt;
247
248use camino::{Utf8Component, Utf8Path, Utf8PathBuf};
249
250pub use crate::{
251 file::{File, FileKind},
252 link::{Link, LinkKind},
253 note::{Note, NoteContext, NoteContextOwned, NoteError, NoteProperties, extract_tags},
254 vault::{SharedVault, Vault, VaultError},
255};
256
257#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize)]
259pub struct VaultPath<'p>(pub &'p Utf8Path);
260
261#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Deserialize)]
263pub struct VaultPathBuf(pub Utf8PathBuf);
264
265impl VaultPathBuf {
266 #[must_use]
268 pub fn as_item(&self, full: &Utf8Path, relative: &Utf8Path) -> ItemPathBuf {
269 ItemPathBuf::new(self, full, relative)
270 }
271
272 #[must_use]
274 pub fn as_ref(&self) -> VaultPath<'_> {
275 VaultPath(self.0.as_path())
276 }
277}
278
279#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize)]
281pub struct ItemPath<'p> {
282 pub vault: VaultPath<'p>,
284
285 pub full: &'p Utf8Path,
287 pub relative: &'p Utf8Path,
289
290 pub slug: &'p Utf8Path,
292}
293
294#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Deserialize)]
296pub struct ItemPathBuf {
297 pub vault: VaultPathBuf,
299
300 pub full: Utf8PathBuf,
302 pub relative: Utf8PathBuf,
304
305 pub slug: Utf8PathBuf,
307}
308
309impl ItemPathBuf {
310 #[must_use]
314 pub fn new(vault: &VaultPathBuf, full: &Utf8Path, relative: &Utf8Path) -> Self {
315 Self {
316 vault: vault.clone(),
317
318 full: full.to_path_buf(),
319 relative: relative.to_path_buf(),
320
321 slug: spluify_path(relative),
322 }
323 }
324
325 #[must_use]
327 pub fn extension(&self) -> Option<&str> {
328 self.full.extension()
329 }
330
331 #[must_use]
333 pub fn as_ref(&self) -> ItemPath<'_> {
334 ItemPath {
335 vault: self.vault.as_ref(),
336 full: &self.full,
337 relative: &self.relative,
338 slug: &self.slug,
339 }
340 }
341}
342
343impl fmt::Display for ItemPathBuf {
344 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345 self.relative.fmt(f)
346 }
347}
348
349#[track_caller]
350fn spluify_path(path: &Utf8Path) -> Utf8PathBuf {
351 let mut path = path.to_path_buf();
352 path.set_extension("");
353
354 let mut new = Utf8PathBuf::new();
355
356 for component in path.components() {
357 if let Utf8Component::Normal(normal) = component {
358 new.push(slug::slugify(normal));
359 }
360 }
361
362 new
363}
364