libzettels 0.4.1

A library intended as a backend for applications which implement Niklas Luhmann's system of a 'Zettelkasten'.
Documentation
//Copyright (c) 2020 Stefan Thesing
//
//This file is part of libzettels.
//
//libzettels is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//libzettels is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with libzettels. If not, see http://www.gnu.org/licenses/.
// --------------------------------------------------------------------------

extern crate libzettels;
extern crate tempfile;
use self::tempfile::tempdir;

use libzettels::{Config, Index, IndexingMethod};
use libzettels::examples::*;
use std::path::PathBuf;
use std::fs::File;
use std::io::Write;

#[test]
fn test_create_index_with_image() {
    let tmp_dir = tempdir().expect("Failed to setup temp dir");
    let dir = tmp_dir.path();
    generate_examples_with_config(dir).expect("Failed to generate examples");
    let config_dir = dir.join("examples/config");
    let cfg_file = config_dir.join("libzettels.cfg.yaml");
    let mut cfg = Config::from_file(cfg_file).expect("Failed to load config");
    cfg.indexingmethod = IndexingMethod::Native;
    
    let rootdir = &cfg.rootdir;
    
    let image_file = rootdir.join("foo.png");
    // Generate an image
    let width: u32 = 10;
    let height: u32 = 10;
    let mut non_text = image::ImageBuffer::new(width, height);
    // color all pixels white
    for (_, _, pixel) in non_text.enumerate_pixels_mut() {
        *pixel = image::Rgb([255, 255, 255]);
    }
    // save it to file
    non_text.save(&image_file).unwrap();
    
    let res = Index::new(&cfg);
    println!("{:?}", res);
    assert!(res.is_ok());
    let index = res.unwrap();
    assert!(!index.files.contains_key(&PathBuf::from("foo.png")));
}

#[test]
fn test_update_index_with_image() {
    let tmp_dir = tempdir().expect("Failed to setup temp dir");
    let dir = tmp_dir.path();
    generate_examples_with_index(dir).expect("Failed to generate examples");
    let config_dir = dir.join("examples/config");
    let cfg_file = config_dir.join("libzettels.cfg.yaml");
    let mut cfg = Config::from_file(cfg_file).expect("Failed to load config");
    cfg.indexingmethod = IndexingMethod::Native;
    let mut index = Index::load(&cfg).expect("Failed to load index");
    let rootdir = &cfg.rootdir;
    
    let image_file = rootdir.join("foo.png");
    // Generate an image
    let width: u32 = 10;
    let height: u32 = 10;
    let mut non_text = image::ImageBuffer::new(width, height);
    // color all pixels white
    for (_, _, pixel) in non_text.enumerate_pixels_mut() {
        *pixel = image::Rgb([255, 255, 255]);
    }
    // save it to file
    non_text.save(&image_file).unwrap();
    
    assert!(index.update(&cfg).is_ok());
    assert!(!index.files.contains_key(&PathBuf::from("foo.png")));
}

#[test]
fn test_create_index_with_svg() {
    let tmp_dir = tempdir().expect("Failed to setup temp dir");
    let dir = tmp_dir.path();

    generate_examples_with_config(dir).expect("Failed to generate examples");
    let config_dir = dir.join("examples/config");
    let cfg_file = config_dir.join("libzettels.cfg.yaml");
    let mut cfg = Config::from_file(cfg_file).expect("Failed to load config");
    cfg.indexingmethod = IndexingMethod::Native;
    
    let rootdir = &cfg.rootdir;
    
    let svg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<svg xmlns=\"http://www.w3.org/2000/svg\"\n\
    xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n\
    version=\"1.1\" baseProfile=\"full\"\n\
    viewBox=\"0 0 5 5\"\n\
    height=\"5mm\"\n\
    width=\"5mm\">\n\
    <title>dummy</title>\n\
    <desc>dummy for testing.</desc>\n\
\n\
<!-- contents -->\n\
\n\
</svg>";
    let mut svg_file = File::create(rootdir.join("image.svg"))
                            .expect("Failed to create file.");
    writeln!(svg_file, "{}", svg ).expect("Failed to write to file.");
    
    let res = Index::new(&cfg);
    println!("{:?}", res);
    assert!(res.is_ok());
    let index = res.unwrap();
    assert!(!index.files.contains_key(&PathBuf::from("image.svg")));
}

#[test]
fn test_update_index_with_svg() {
    let tmp_dir = tempdir().expect("Failed to setup temp dir");
    let dir = tmp_dir.path();

    generate_examples_with_index(dir).expect("Failed to generate examples");
    let config_dir = dir.join("examples/config");
    let cfg_file = config_dir.join("libzettels.cfg.yaml");
    let mut cfg = Config::from_file(cfg_file).expect("Failed to load config");
    cfg.indexingmethod = IndexingMethod::Native;
    let mut index = Index::load(&cfg).expect("Failed to load index");
    let rootdir = &cfg.rootdir;
    
    let svg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<svg xmlns=\"http://www.w3.org/2000/svg\"\n\
    xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n\
    version=\"1.1\" baseProfile=\"full\"\n\
    viewBox=\"0 0 5 5\"\n\
    height=\"5mm\"\n\
    width=\"5mm\">\n\
    <title>dummy</title>\n\
    <desc>dummy for testing.</desc>\n\
\n\
<!-- contents -->\n\
\n\
</svg>";
    let mut svg_file = File::create(rootdir.join("image.svg"))
                            .expect("Failed to create file.");
    writeln!(svg_file, "{}", svg ).expect("Failed to write to file.");
    
    assert!(index.update(&cfg).is_ok());
    assert!(!index.files.contains_key(&PathBuf::from("image.svg")));
    
}


#[test]
fn test_image_based_zettel() {
    let tmp_dir = tempdir().expect("Failed to setup temp dir");
    let dir = tmp_dir.path();
    generate_examples_with_index(dir).expect("Failed to generate examples");
    
    let config_dir = dir.join("examples/config");
    let cfg_file = config_dir.join("libzettels.cfg.yaml");
    let mut cfg = Config::from_file(cfg_file).expect("Failed to load config");
    cfg.indexingmethod = IndexingMethod::Grep;
    
    let mut index = Index::load(&cfg).expect("Failed to load index");
    
    let rootdir = &cfg.rootdir;
    
    let image_file = rootdir.join("foo.png");
    // Generate an image
    let width: u32 = 10;
    let height: u32 = 10;
    let mut non_text = image::ImageBuffer::new(width, height);
    // color all pixels white
    for (_, _, pixel) in non_text.enumerate_pixels_mut() {
        *pixel = image::Rgb([255, 255, 255]);
    }
    // save it to file
    non_text.save(&image_file).unwrap();
    
    // A zettel file holding the metadata
    let metadata = "---
    title:  'Image-based Zettel'
    keywords: [example, image]
    followups: []
    links: [file2.md, file3.md]
    ...
    ![scanned zettel](foo.png)";
    let mut zettel = File::create(rootdir.join("image_based_zettel.md"))
                            .expect("Failed to create file.");
    writeln!(zettel, "{}", metadata).expect("Failed to write to file.");
    
    // Update the index
    index.update(&cfg).expect("Failed to update index.");
    // Check if the metadata-zettel is there, but the image itself isn't.
    assert!(index.files.contains_key(&PathBuf::from("image_based_zettel.md")));
    assert_eq!(index.files.contains_key(&PathBuf::from("foo.png")), false);
    
    // retrieve the zettel and check its metadata
    let z = index.get_zettel("image_based_zettel.md").unwrap();
    assert_eq!(z.title, "Image-based Zettel");
    assert_eq!(z.links.len(), 2);
    assert!(z.links.contains(&PathBuf::from("file2.md")));
    assert!(z.links.contains(&PathBuf::from("file3.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"image".to_string()));
}