1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
//! Tools to build custom `Pipeline`s that aren't already provided. //! //! Using the tools here to build custom [`Pipelines`] can help keep your //! pipelines more consistent, and easier to use for others. //! //! [`Pipelines`]: ../trait.Pipeline.html use self::Filter::*; use regex::Regex; use std::path::Path; /// The type of filter list to use. pub enum FilterListType { Blacklist, Whitelist, } /// A filter to determine if a file or path should be added to the `Pipeline`. pub enum Filter { Include(FilterRule), Exclude(FilterRule), } impl Filter { /// Create a filter that includes a file extension. /// /// Can panic, see [`FilterRule::extension`]. /// /// [`FilterRule::extension`]: ./enum.FilterRule.html#method.extension pub fn include_extension<S: Into<String>>(ext: S) -> Self { Include(FilterRule::extension(ext)) } /// Create a filter that excludes a file extension. /// /// Can panic, see [`FilterRule::extension`]. /// /// [`FilterRule::extension`]: ./enum.FilterRule.html#method.extension pub fn exclude_extension<S: Into<String>>(ext: S) -> Self { Exclude(FilterRule::extension(ext)) } /// Create a filter that includes a regex. /// /// Can panic, see [`FilterRule::regex`]. /// /// [`FilterRule::regex`]: ./enum.FilterRule.html#method.regex pub fn include_regex<S: AsRef<str>>(regex_str: S) -> Self { Include(FilterRule::regex(regex_str)) } /// Create a filter that excludes a regex. /// /// Can panic, see [`FilterRule::regex`]. /// /// [`FilterRule::regex`]: ./enum.FilterRule.html#method.regex pub fn exclude_regex<S: AsRef<str>>(regex_str: S) -> Self { Exclude(FilterRule::regex(regex_str)) } pub fn matches<P: AsRef<Path>>(&self, relative_path: P) -> bool { match self { Include(rule) => rule.matches(relative_path), Exclude(rule) => rule.matches(relative_path), } } } /// A rule on how to match a file or path pub enum FilterRule { /// Match any file that contains the specified extension. /// /// It is suggested to use the [`extension`] helper method instead for /// ease of use and consistency. /// /// ``` /// # use includer_codegen::utils::FilterRule; /// # /// let html_files = FilterRule::Extension("html".to_string()); /// let inconsistent = FilterRule::Extension(".html".to_string()); /// ``` /// /// Note: For consistency, the extension should *not* have a leading period /// /// [`extension`]: #method.extension Extension(String), /// Match any file that has a regex match on its path. /// /// It is suggested to use the [`regex`] helper method instead for /// ease of use and consistency. /// /// ``` /// # use includer_codegen::utils::FilterRule; /// use includer_codegen::regex::Regex; /// /// // Match all css files in the "styles" subdirectory /// let css_files = FilterRule::Regex(Regex::new(r"^styles[/\\].*\.css$").unwrap()); /// ``` /// /// Note: For consistency, the path compared to the regex should be /// relative to the root asset path with no leading slash. You can get /// this result by using [`strip_prefix`]. /// /// [`regex`]: #method.regex /// [`strip_prefix`]: https://doc.rust-lang.org/std/path/struct.Path.html#method.strip_prefix Regex(Regex), } impl FilterRule { /// Creates a validated `FilterRule::Extension` /// /// Makes sure that the extension does not have a leading `"."`. /// /// ``` /// # use includer_codegen::utils::FilterRule; /// # /// // Only accept HTML files /// FilterRule::extension("html"); /// ``` /// /// # Panics /// /// This function will panic if extension is not valid. /// /// ```should_panic /// # use includer_codegen::utils::FilterRule; /// # /// // should panic /// FilterRule::extension(".html"); /// ``` pub fn extension<S: Into<String>>(extension: S) -> Self { let ext = extension.into(); if &ext[0..1] == "." { panic!("Filter::Extension should not contain a period prefix!"); } FilterRule::Extension(ext) } /// Creates a validated `Filer::Regex` /// /// ``` /// # use includer_codegen::utils::FilterRule; /// # /// // Accept all css files that are under the root subdirectory `styles` (multi-platform) /// FilterRule::regex(r"^styles[/\\].*\.css$"); /// ``` /// /// # Panics /// /// Invalid regex expressions will panic. /// /// ```should_panic /// # use includer_codegen::utils::FilterRule; /// # /// // should panic /// FilterRule::regex(r"\h"); /// ``` pub fn regex<S: AsRef<str>>(regex_str: S) -> Self { let regex = Regex::new(regex_str.as_ref()); FilterRule::Regex(regex.unwrap()) } /// See if the path matches the filter rule pub fn matches<P: AsRef<Path>>(&self, relative_path: P) -> bool { let path = relative_path.as_ref(); match self { FilterRule::Extension(ext) => path.extension() == Some(ext.as_ref()), FilterRule::Regex(re) => re.is_match( path.to_str() .expect("Path couldn't be represented by a str"), ), } } } pub(crate) fn path_to_string<P: AsRef<Path>>(path: P) -> String { path.as_ref() .to_str() .expect("Unable to represent path as str") .to_string() } /// Makes Cargo re-run build script if path has changed since last build. /// /// Note this only has an effect inside a build script, as it just prints a /// Cargo interpreted key to stdout. See [`reference`]. /// /// # Panics /// /// Panics if the path cannot be casted to a str. /// /// [`reference`]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script pub fn watch_path<P: AsRef<Path>>(p: P) { println!("cargo:rerun-if-changed={}", p.as_ref().to_str().unwrap()); }