Example frontmatter-inclusion with closure

This commit is contained in:
Nick Groenen 2022-01-08 13:24:10 +01:00
parent 86af6bbf37
commit 00e0f70d1d
No known key found for this signature in database
GPG Key ID: 4F0AD019928AE098
2 changed files with 54 additions and 1 deletions

View File

@ -1,6 +1,6 @@
use eyre::{eyre, Result};
use gumdrop::Options;
use obsidian_export::postprocessors::softbreaks_to_hardbreaks;
use obsidian_export::postprocessors::{create_yaml_includer, softbreaks_to_hardbreaks};
use obsidian_export::{ExportError, Exporter, FrontmatterStrategy, WalkOptions};
use std::{env, path::PathBuf};
@ -54,6 +54,21 @@ struct Opts {
default = "false"
)]
hard_linebreaks: bool,
#[options(
no_short,
long = "front-matter-inclusion-key",
help = "Only include files with the specified YAML key set to 'true'"
)]
front_matter_inclusion: String,
#[options(
no_short,
long = "exclude-embeds-by-frontmatter",
help = "Exclude all embeds that do not have the front-matter-inclusion-key",
default = "false"
)]
embeded_front_matter_inclusion: bool,
}
fn frontmatter_strategy_from_str(input: &str) -> Result<FrontmatterStrategy> {
@ -90,6 +105,19 @@ fn main() {
exporter.process_embeds_recursively(!args.no_recursive_embeds);
exporter.walk_options(walk_options);
// Here we call create_yaml_includer() with the user-supplied frontmatter inclusion key.
//
// Calling this function returns a closure which matches the signature of a postprocessor,
// meaning we can pass the result to add_postprocessor() later.
let yaml_postprocessor = create_yaml_includer(&args.front_matter_inclusion);
if args.front_matter_inclusion.len() > 0 {
exporter.add_postprocessor(&yaml_postprocessor);
if args.embeded_front_matter_inclusion {
exporter.add_embed_postprocessor(&yaml_postprocessor);
}
}
if args.hard_linebreaks {
exporter.add_postprocessor(&softbreaks_to_hardbreaks);
}

View File

@ -2,6 +2,7 @@
use super::{Context, MarkdownEvents, PostprocessorResult};
use pulldown_cmark::Event;
use serde_yaml::Value;
/// This postprocessor converts all soft line breaks to hard line breaks. Enabling this mimics
/// Obsidian's _'Strict line breaks'_ setting.
@ -18,3 +19,27 @@ pub fn softbreaks_to_hardbreaks(
.collect();
(context, events, PostprocessorResult::Continue)
}
// This function takes as input the YAML key to look for, then returns a new function (technically:
// a closure) which matches the signature of a postprocessor.
//
// This use of dynamic function building allows the capturing of the configuration (in this case
// the YAML key) without needing to store this data within the Exporter struct.
//
// (Ideally we could mark the return value as `-> impl Postprocessor` for readability, but we
// cannot use a type alias here, which is what `Postprocessor` is)
pub fn create_yaml_includer(
yaml_inclusion_key: &str,
) -> impl Fn(Context, MarkdownEvents) -> (Context, MarkdownEvents, PostprocessorResult) {
let key = serde_yaml::Value::String(yaml_inclusion_key.to_string());
// This bit creates and returns the closure. The `move` statement is needed to make it take
// ownership of `key` above.
move |context: Context, events: MarkdownEvents| {
let action = match context.frontmatter.get(&key) {
Some(Value::Bool(true)) => PostprocessorResult::Continue,
_ => PostprocessorResult::StopAndSkipNote,
};
(context, events, action)
}
}