You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
4.3KB

  1. use std::collections::HashMap;
  2. use std::path::{PathBuf};
  3. use tera::{GlobalFn, Value, from_value, to_value, Result};
  4. use content::{Page, Section};
  5. use config::Config;
  6. use utils::site::resolve_internal_link;
  7. pub fn make_get_page(all_pages: &HashMap<PathBuf, Page>) -> GlobalFn {
  8. let mut pages = HashMap::new();
  9. for page in all_pages.values() {
  10. pages.insert(page.file.relative.clone(), page.clone());
  11. }
  12. Box::new(move |args| -> Result<Value> {
  13. match args.get("path") {
  14. Some(val) => match from_value::<String>(val.clone()) {
  15. Ok(v) => {
  16. match pages.get(&v) {
  17. Some(p) => Ok(to_value(p).unwrap()),
  18. None => Err(format!("Page `{}` not found.", v).into())
  19. }
  20. },
  21. Err(_) => Err(format!("`get_page` received path={:?} but it requires a string", val).into()),
  22. },
  23. None => Err("`get_page` requires a `path` argument.".into()),
  24. }
  25. })
  26. }
  27. pub fn make_get_section(all_sections: &HashMap<PathBuf, Section>) -> GlobalFn {
  28. let mut sections = HashMap::new();
  29. for section in all_sections.values() {
  30. sections.insert(section.file.relative.clone(), section.clone());
  31. }
  32. Box::new(move |args| -> Result<Value> {
  33. match args.get("path") {
  34. Some(val) => match from_value::<String>(val.clone()) {
  35. Ok(v) => {
  36. match sections.get(&v) {
  37. Some(p) => Ok(to_value(p).unwrap()),
  38. None => Err(format!("Section `{}` not found.", v).into())
  39. }
  40. },
  41. Err(_) => Err(format!("`get_section` received path={:?} but it requires a string", val).into()),
  42. },
  43. None => Err("`get_section` requires a `path` argument.".into()),
  44. }
  45. })
  46. }
  47. pub fn make_get_url(permalinks: HashMap<String, String>, config: Config) -> GlobalFn {
  48. Box::new(move |args| -> Result<Value> {
  49. let cachebust = args
  50. .get("cachebust")
  51. .map_or(false, |c| {
  52. from_value::<bool>(c.clone()).unwrap_or(false)
  53. });
  54. if args.contains_key("link") {
  55. println!("> DEPRECATION -- `link` is deprecated for `get_url`: use `path` instead");
  56. }
  57. match args.get("link").or_else(|| args.get("path")) {
  58. Some(val) => match from_value::<String>(val.clone()) {
  59. Ok(v) => {
  60. // Internal link
  61. if v.starts_with("./") {
  62. match resolve_internal_link(&v, &permalinks) {
  63. Ok(url) => Ok(to_value(url).unwrap()),
  64. Err(_) => Err(format!("Could not resolve URL for link `{}` not found.", v).into())
  65. }
  66. } else {
  67. // anything else
  68. let mut permalink = config.make_permalink(&v);
  69. if cachebust {
  70. permalink = format!("{}?t={}", permalink, config.build_timestamp.unwrap());
  71. }
  72. Ok(to_value(permalink).unwrap())
  73. }
  74. },
  75. Err(_) => Err(format!("`get_url` received path={:?} but it requires a string", val).into()),
  76. },
  77. None => Err("`get_url` requires a `path` argument.".into()),
  78. }
  79. })
  80. }
  81. #[cfg(test)]
  82. mod tests {
  83. use super::make_get_url;
  84. use std::collections::HashMap;
  85. use tera::to_value;
  86. use config::Config;
  87. #[test]
  88. fn can_add_cachebust_to_url() {
  89. let config = Config::default();
  90. let static_fn = make_get_url(HashMap::new(), config);
  91. let mut args = HashMap::new();
  92. args.insert("path".to_string(), to_value("app.css").unwrap());
  93. args.insert("cachebust".to_string(), to_value(true).unwrap());
  94. assert_eq!(static_fn(args).unwrap(), "http://a-website.com/app.css/?t=1");
  95. }
  96. #[test]
  97. fn can_link_to_some_static_file() {
  98. let config = Config::default();
  99. let static_fn = make_get_url(HashMap::new(), config);
  100. let mut args = HashMap::new();
  101. args.insert("path".to_string(), to_value("app.css").unwrap());
  102. assert_eq!(static_fn(args).unwrap(), "http://a-website.com/app.css/");
  103. }
  104. }