Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft for partial file ignoring with tags. #159

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub extern crate serde_yaml;
extern crate lazy_static;

mod context;
mod preprocessors;
mod frontmatter;
pub mod postprocessors;
mod references;
Expand Down Expand Up @@ -132,7 +133,8 @@ pub type MarkdownEvents<'a> = Vec<Event<'a>>;
/// exporter.add_postprocessor(&foo_to_bar);
/// # exporter.run().unwrap();
/// ```

pub type Preprocessor =
dyn Fn(&mut Context, &mut String) -> PostprocessorResult + Send + Sync;
pub type Postprocessor =
dyn Fn(&mut Context, &mut MarkdownEvents) -> PostprocessorResult + Send + Sync;
type Result<T, E = ExportError> = std::result::Result<T, E>;
Expand Down Expand Up @@ -231,6 +233,7 @@ pub struct Exporter<'a> {
vault_contents: Option<Vec<PathBuf>>,
walk_options: WalkOptions<'a>,
process_embeds_recursively: bool,
preprocessors: Vec<&'a Preprocessor>,
postprocessors: Vec<&'a Postprocessor>,
embed_postprocessors: Vec<&'a Postprocessor>,
}
Expand Down Expand Up @@ -274,6 +277,7 @@ impl<'a> Exporter<'a> {
walk_options: WalkOptions::default(),
process_embeds_recursively: true,
vault_contents: None,
preprocessors: vec![&preprocessors::remove_ignore_blocks],
postprocessors: vec![],
embed_postprocessors: vec![],
}
Expand Down Expand Up @@ -381,7 +385,7 @@ impl<'a> Exporter<'a> {
.strip_prefix(&self.start_at.clone())
.expect("file should always be nested under root")
.to_path_buf();
let destination = &self.destination.join(&relative_path);
let destination = &self.destination.join(relative_path);
self.export_note(&file, destination)
})?;
Ok(())
Expand All @@ -398,7 +402,7 @@ impl<'a> Exporter<'a> {
fn parse_and_export_obsidian_note(&self, src: &Path, dest: &Path) -> Result<()> {
let mut context = Context::new(src.to_path_buf(), dest.to_path_buf());

let (frontmatter, mut markdown_events) = self.parse_obsidian_note(src, &context)?;
let (frontmatter, mut markdown_events) = self.parse_obsidian_note(src, &mut context)?;
context.frontmatter = frontmatter;
for func in &self.postprocessors {
match func(&mut context, &mut markdown_events) {
Expand Down Expand Up @@ -432,14 +436,17 @@ impl<'a> Exporter<'a> {
fn parse_obsidian_note<'b>(
&self,
path: &Path,
context: &Context,
context: &mut Context,
) -> Result<(Frontmatter, MarkdownEvents<'b>)> {
if context.note_depth() > NOTE_RECURSION_LIMIT {
return Err(ExportError::RecursionLimitExceeded {
file_tree: context.file_tree(),
});
}
let content = fs::read_to_string(path).context(ReadSnafu { path })?;
let mut content = fs::read_to_string(path).context(ReadSnafu { path })?;
for preprocessor in &self.preprocessors {
preprocessor(context, &mut content);
}
let (frontmatter, content) =
matter::matter(&content).unwrap_or(("".to_string(), content.to_string()));
let frontmatter =
Expand Down Expand Up @@ -598,7 +605,7 @@ impl<'a> Exporter<'a> {

let events = match path.extension().unwrap_or(&no_ext).to_str() {
Some("md") => {
let (frontmatter, mut events) = self.parse_obsidian_note(path, &child_context)?;
let (frontmatter, mut events) = self.parse_obsidian_note(path, &mut child_context)?;
child_context.frontmatter = frontmatter;
if let Some(section) = note_ref.section {
events = reduce_to_section(events, section);
Expand Down Expand Up @@ -647,9 +654,9 @@ impl<'a> Exporter<'a> {
Ok(events)
}

fn make_link_to_file<'b, 'c>(
fn make_link_to_file<'c>(
&self,
reference: ObsidianNoteReference<'b>,
reference: ObsidianNoteReference<'_>,
context: &Context,
) -> MarkdownEvents<'c> {
let target_file = reference
Expand Down Expand Up @@ -732,7 +739,7 @@ fn lookup_filename_in_vault<'a>(

path_normalized.ends_with(&filename_normalized)
|| path_normalized.ends_with(filename_normalized.clone() + ".md")
|| path_normalized_lowered.ends_with(&filename_normalized.to_lowercase())
|| path_normalized_lowered.ends_with(filename_normalized.to_lowercase())
|| path_normalized_lowered.ends_with(filename_normalized.to_lowercase() + ".md")
})
}
Expand Down Expand Up @@ -783,7 +790,7 @@ fn is_markdown_file(file: &Path) -> bool {

/// Reduce a given `MarkdownEvents` to just those elements which are children of the given section
/// (heading name).
fn reduce_to_section<'a, 'b>(events: MarkdownEvents<'a>, section: &'b str) -> MarkdownEvents<'a> {
fn reduce_to_section<'a>(events: MarkdownEvents<'a>, section: &'_ str) -> MarkdownEvents<'a> {
let mut filtered_events = Vec::with_capacity(events.len());
let mut target_section_encountered = false;
let mut currently_in_target_section = false;
Expand Down
20 changes: 20 additions & 0 deletions src/preprocessors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! A collection of officially maintained [postprocessors][crate::Postprocessor].

use super::{Context, PostprocessorResult};
use regex::Regex;

const IGNORE_REGEX_0: &str = r"%% EXPORT_IGNORE_BEGIN %%(.|\n)*?%% EXPORT_IGNORE_END %%";
const IGNORE_REGEX_1: &str = r"# EXPORT_IGNORE_BEGIN(.|\n)*?# EXPORT_IGNORE_END";

/// This postprocessor removes all
pub fn remove_ignore_blocks(
_context: &mut Context,
string: &mut String,
) -> PostprocessorResult {
let re = Regex::new(IGNORE_REGEX_0).unwrap();
*string = re.replace_all(string, "").to_string();

let re = Regex::new(IGNORE_REGEX_1).unwrap();
*string = re.replace_all(string, "").to_string();
PostprocessorResult::Continue
}