Created
October 2, 2017 19:10
-
-
Save Geobert/84e2d4962ca7e5a77f3a9dfe40ac372a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use datetime; | |
use serde_yaml; | |
use liquid; | |
use std::fs::File; | |
use std::io::Write; | |
use std::path::Path; | |
use super::super::document::{read_file, split_document}; | |
use frontmatter::FrontmatterBuilder; | |
use error::{ErrorKind, Result}; | |
#[derive(Debug, Default, Clone, Eq, PartialEq)] | |
#[derive(Serialize, Deserialize)] | |
#[serde(deny_unknown_fields, default)] | |
struct JkPostFrontmatter { | |
pub layout: Option<String>, | |
pub permalink: Option<String>, | |
pub published: bool, | |
pub date: Option<datetime::DateTime>, | |
pub category: Option<String>, | |
pub categories: Option<Vec<String>>, | |
pub tags: Option<Vec<String>>, | |
pub title: String, | |
pub excerpt: Option<String>, | |
pub path: String, | |
pub custom: liquid::Object, | |
} | |
impl From<JkPostFrontmatter> for FrontmatterBuilder { | |
fn from(jekyll: JkPostFrontmatter) -> Self { | |
let builder = FrontmatterBuilder::new() | |
.merge_title(jekyll.title) | |
.merge_layout(jekyll.layout) | |
.merge_published_date(jekyll.date) | |
.merge_description(jekyll.excerpt) | |
.merge_path(jekyll.path) | |
.merge_custom(jekyll.custom); | |
if let Some(cat) = jekyll.category { | |
builder.merge_categories(vec![cat]) | |
} else if let Some(categories) = jekyll.categories { | |
builder.merge_categories(categories) | |
} else { | |
builder | |
} | |
// TODO merge tags when cobalt's frontmatter allows it | |
} | |
} | |
#[derive(Debug, Default, Clone, Eq, PartialEq)] | |
#[derive(Serialize, Deserialize)] | |
pub struct JkDocument { | |
pub front: Option<String>, | |
pub content: Option<String>, | |
} | |
impl JkDocument { | |
pub fn parse_string(doc: String) -> Result<JkDocument> { | |
let (front, content) = split_document(&doc)?; | |
if front != None { | |
Err(ErrorKind::MissingFrontStart.into()) | |
} else { | |
match split_document(&content)? { | |
(None, _) => Err(ErrorKind::MissingFrontmatter.into()), | |
(Some(front), content) => Ok(JkDocument { | |
front: Some(front.to_owned()), | |
content: Some(content.to_owned()), | |
}), | |
} | |
} | |
} | |
pub fn parse(source_file: &Path) -> Result<JkDocument> { | |
let doc: String = read_file(source_file)?; | |
JkDocument::parse_string(doc) | |
} | |
pub fn convert_front(front: &str) -> Result<String> { | |
let front_yaml: JkPostFrontmatter = serde_yaml::from_str(front)?; | |
let front_builder: FrontmatterBuilder = front_yaml.into(); | |
let front = front_builder.build()?; | |
Ok(serde_yaml::to_string(&front)?) | |
} | |
pub fn convert(source_file: &Path, dest_file: &Path) -> Result<()> { | |
let doc = JkDocument::parse(source_file)?; | |
let front = JkDocument::convert_front(&doc.front.unwrap())?; | |
let mut dest = File::create(dest_file)?; | |
let converted = format!("{}---\n{}", &front, &doc.content.unwrap()); | |
dest.write_all(converted.as_bytes())?; | |
Ok(()) | |
} | |
} | |
#[cfg(test)] | |
mod test { | |
use super::*; | |
use error::{ErrorKind, Result}; | |
fn get_correct_cb_front() -> &'static str { | |
r#"title: test_post | |
published_date: 2017-05-03T20:55:07+00:00 | |
layout: post | |
path: /2017/05/03/test_post/ | |
categories: | |
- cat1 | |
- cat2 | |
"# | |
} | |
fn get_correct_jk_front() -> &'static str { | |
r#"id: 33 | |
title: test_post | |
date: 2017-05-03T20:55:07+00:00 | |
author: TheAuthor | |
layout: post | |
guid: http://url.com/?p=33 | |
permalink: /2017/05/03/test_post/ | |
categories: | |
- cat1 | |
- cat2 | |
tags: | |
- tag1 | |
- tag2 | |
- tag3 | |
"# | |
} | |
fn get_correct_content() -> &'static str { | |
"the content\n" | |
} | |
#[test] | |
fn parse_string_ok() { | |
let correct_front = get_correct_jk_front(); | |
let correct_content = get_correct_content(); | |
let correct_doc = format!("---\n{}---\n{}", correct_front, correct_content); | |
let res = JkDocument::parse_string(correct_doc); | |
assert!(res.is_ok()); | |
let doc = res.unwrap(); | |
assert_eq!(doc.content.unwrap(), correct_content); | |
assert_eq!(doc.front.unwrap(), correct_front); | |
} | |
#[test] | |
fn parse_string_no_front() { | |
let res = JkDocument::parse_string(get_correct_content().to_owned()); | |
assert!(res.is_err()); | |
//assert_eq!(res.unwrap_err(), ErrorKind::MissingFrontmatter); | |
} | |
#[test] | |
fn parse_string_no_front_starter() { | |
let correct_front = get_correct_jk_front(); | |
let correct_content = get_correct_content(); | |
let correct_doc = format!("{}---\n{}", correct_front, correct_content); | |
let res = JkDocument::parse_string(correct_doc); | |
assert!(res.is_err()); | |
//assert_eq!(res.unwrap_err(), ErrorKind::MissingFrontStart); | |
} | |
#[test] | |
fn convert_front_ok() { | |
let correct_front = get_correct_jk_front(); | |
let res = JkDocument::convert_front(correct_front); | |
match res { | |
Err(e) => println!("error convert: {:#?}", e), | |
Ok(converted) => assert_eq!(converted, get_correct_cb_front()), | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment