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.

123 lines
3.6KB

  1. use std::path::Path;
  2. use regex::Regex;
  3. use errors::{Result, ResultExt};
  4. mod page;
  5. mod section;
  6. pub use self::page::PageFrontMatter;
  7. pub use self::section::{SectionFrontMatter, InsertAnchor};
  8. lazy_static! {
  9. static ref PAGE_RE: Regex = Regex::new(r"^[[:space:]]*\+\+\+\r?\n((?s).*?(?-s))\+\+\+\r?\n?((?s).*(?-s))$").unwrap();
  10. }
  11. /// Split a file between the front matter and its content
  12. /// Will return an error if the front matter wasn't found
  13. fn split_content(file_path: &Path, content: &str) -> Result<(String, String)> {
  14. if !PAGE_RE.is_match(content) {
  15. bail!("Couldn't find front matter in `{}`. Did you forget to add `+++`?", file_path.to_string_lossy());
  16. }
  17. // 2. extract the front matter and the content
  18. let caps = PAGE_RE.captures(content).unwrap();
  19. // caps[0] is the full match
  20. // caps[1] => front matter
  21. // caps[2] => content
  22. Ok((caps[1].to_string(), caps[2].to_string()))
  23. }
  24. /// Split a file between the front matter and its content.
  25. /// Returns a parsed `SectionFrontMatter` and the rest of the content
  26. pub fn split_section_content(file_path: &Path, content: &str) -> Result<(SectionFrontMatter, String)> {
  27. let (front_matter, content) = split_content(file_path, content)?;
  28. let meta = SectionFrontMatter::parse(&front_matter)
  29. .chain_err(|| format!("Error when parsing front matter of section `{}`", file_path.to_string_lossy()))?;
  30. Ok((meta, content))
  31. }
  32. /// Split a file between the front matter and its content
  33. /// Returns a parsed `PageFrontMatter` and the rest of the content
  34. pub fn split_page_content(file_path: &Path, content: &str) -> Result<(PageFrontMatter, String)> {
  35. let (front_matter, content) = split_content(file_path, content)?;
  36. let meta = PageFrontMatter::parse(&front_matter)
  37. .chain_err(|| format!("Error when parsing front matter of section `{}`", file_path.to_string_lossy()))?;
  38. Ok((meta, content))
  39. }
  40. #[cfg(test)]
  41. mod tests {
  42. use std::path::Path;
  43. use super::{split_section_content, split_page_content};
  44. #[test]
  45. fn can_split_page_content_valid() {
  46. let content = r#"
  47. +++
  48. title = "Title"
  49. description = "hey there"
  50. date = "2002/10/12"
  51. +++
  52. Hello
  53. "#;
  54. let (front_matter, content) = split_page_content(Path::new(""), content).unwrap();
  55. assert_eq!(content, "Hello\n");
  56. assert_eq!(front_matter.title.unwrap(), "Title");
  57. }
  58. #[test]
  59. fn can_split_section_content_valid() {
  60. let content = r#"
  61. +++
  62. paginate_by = 10
  63. +++
  64. Hello
  65. "#;
  66. let (front_matter, content) = split_section_content(Path::new(""), content).unwrap();
  67. assert_eq!(content, "Hello\n");
  68. assert!(front_matter.is_paginated());
  69. }
  70. #[test]
  71. fn can_split_content_with_only_frontmatter_valid() {
  72. let content = r#"
  73. +++
  74. title = "Title"
  75. description = "hey there"
  76. date = "2002/10/12"
  77. +++"#;
  78. let (front_matter, content) = split_page_content(Path::new(""), content).unwrap();
  79. assert_eq!(content, "");
  80. assert_eq!(front_matter.title.unwrap(), "Title");
  81. }
  82. #[test]
  83. fn can_split_content_lazily() {
  84. let content = r#"
  85. +++
  86. title = "Title"
  87. description = "hey there"
  88. date = "2002-10-02T15:00:00Z"
  89. +++
  90. +++"#;
  91. let (front_matter, content) = split_page_content(Path::new(""), content).unwrap();
  92. assert_eq!(content, "+++");
  93. assert_eq!(front_matter.title.unwrap(), "Title");
  94. }
  95. #[test]
  96. fn errors_if_cannot_locate_frontmatter() {
  97. let content = r#"
  98. +++
  99. title = "Title"
  100. description = "hey there"
  101. date = "2002/10/12""#;
  102. let res = split_page_content(Path::new(""), content);
  103. assert!(res.is_err());
  104. }
  105. }