Add a lifetime annotation to the Postprocesor type
This lets the compiler reason about the lifetimes of objects used by the postprocessor, if the callback captures variables. See zoni/obsidian-export#175
This commit is contained in:
parent
c27d7b96b6
commit
cd5dbf6c3b
@ -133,8 +133,8 @@ pub type MarkdownEvents<'a> = Vec<Event<'a>>;
|
|||||||
/// # exporter.run().unwrap();
|
/// # exporter.run().unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
pub type Postprocessor =
|
pub type Postprocessor<'f> =
|
||||||
dyn Fn(&mut Context, &mut MarkdownEvents) -> PostprocessorResult + Send + Sync;
|
dyn Fn(&mut Context, &mut MarkdownEvents) -> PostprocessorResult + Send + Sync + 'f;
|
||||||
type Result<T, E = ExportError> = std::result::Result<T, E>;
|
type Result<T, E = ExportError> = std::result::Result<T, E>;
|
||||||
|
|
||||||
const PERCENTENCODE_CHARS: &AsciiSet = &CONTROLS.add(b' ').add(b'(').add(b')').add(b'%').add(b'?');
|
const PERCENTENCODE_CHARS: &AsciiSet = &CONTROLS.add(b' ').add(b'(').add(b')').add(b'%').add(b'?');
|
||||||
@ -231,8 +231,8 @@ pub struct Exporter<'a> {
|
|||||||
vault_contents: Option<Vec<PathBuf>>,
|
vault_contents: Option<Vec<PathBuf>>,
|
||||||
walk_options: WalkOptions<'a>,
|
walk_options: WalkOptions<'a>,
|
||||||
process_embeds_recursively: bool,
|
process_embeds_recursively: bool,
|
||||||
postprocessors: Vec<&'a Postprocessor>,
|
postprocessors: Vec<&'a Postprocessor<'a>>,
|
||||||
embed_postprocessors: Vec<&'a Postprocessor>,
|
embed_postprocessors: Vec<&'a Postprocessor<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> fmt::Debug for Exporter<'a> {
|
impl<'a> fmt::Debug for Exporter<'a> {
|
||||||
|
@ -3,8 +3,10 @@ use obsidian_export::{Context, Exporter, MarkdownEvents, PostprocessorResult};
|
|||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use pulldown_cmark::{CowStr, Event};
|
use pulldown_cmark::{CowStr, Event};
|
||||||
use serde_yaml::Value;
|
use serde_yaml::Value;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::fs::{read_to_string, remove_file};
|
use std::fs::{read_to_string, remove_file};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Mutex;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
/// This postprocessor replaces any instance of "foo" with "bar" in the note body.
|
/// This postprocessor replaces any instance of "foo" with "bar" in the note body.
|
||||||
@ -105,6 +107,38 @@ fn test_postprocessor_change_destination() {
|
|||||||
assert!(new_note_path.exists());
|
assert!(new_note_path.exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure postprocessor type definition has proper lifetimes to allow state (here: `parents`)
|
||||||
|
// to be passed in. Otherwise, this fails with an error like:
|
||||||
|
// error[E0597]: `parents` does not live long enough
|
||||||
|
// cast requires that `parents` is borrowed for `'static`
|
||||||
|
#[test]
|
||||||
|
fn test_postprocessor_stateful_callback() {
|
||||||
|
let tmp_dir = TempDir::new().expect("failed to make tempdir");
|
||||||
|
let mut exporter = Exporter::new(
|
||||||
|
PathBuf::from("tests/testdata/input/postprocessors"),
|
||||||
|
tmp_dir.path().to_path_buf(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let parents: Mutex<HashSet<PathBuf>> = Default::default();
|
||||||
|
let callback = |ctx: &mut Context, _mdevents: &mut MarkdownEvents| -> PostprocessorResult {
|
||||||
|
parents
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.insert(ctx.destination.parent().unwrap().to_path_buf());
|
||||||
|
PostprocessorResult::Continue
|
||||||
|
};
|
||||||
|
exporter.add_postprocessor(&callback);
|
||||||
|
|
||||||
|
exporter.run().unwrap();
|
||||||
|
|
||||||
|
let expected = tmp_dir.path().clone();
|
||||||
|
|
||||||
|
let parents = parents.lock().unwrap();
|
||||||
|
println!("{:?}", parents);
|
||||||
|
assert_eq!(1, parents.len());
|
||||||
|
assert!(parents.contains(expected));
|
||||||
|
}
|
||||||
|
|
||||||
// The purpose of this test to verify the `append_frontmatter` postprocessor is called to extend
|
// The purpose of this test to verify the `append_frontmatter` postprocessor is called to extend
|
||||||
// the frontmatter, and the `foo_to_bar` postprocessor is called to replace instances of "foo" with
|
// the frontmatter, and the `foo_to_bar` postprocessor is called to replace instances of "foo" with
|
||||||
// "bar" (only in the note body).
|
// "bar" (only in the note body).
|
||||||
|
Loading…
Reference in New Issue
Block a user