From 84308c9f1f4f4f0a503497d435cb7303710de0b9 Mon Sep 17 00:00:00 2001 From: Nick Groenen Date: Sun, 2 Jan 2022 00:42:51 +0100 Subject: [PATCH] New: support Obsidian's "Strict line breaks" setting This change introduces a new `--hard-linebreaks` CLI argument. When used, this converts soft line breaks to hard line breaks, mimicking Obsidian's "Strict line breaks" setting. Implementation detail: I considered naming this flag `--strict-line-breaks` to be consistent with Obsidian itself, however I feel the name is somewhat misleading and ill-chosen. --- src/lib.rs | 1 + src/main.rs | 12 ++++++++++ src/postprocessors.rs | 20 ++++++++++++++++ tests/postprocessors_test.rs | 23 +++++++++++++++++++ .../postprocessors/hard_linebreaks.md | 18 +++++++++++++++ .../input/postprocessors/hard_linebreaks.md | 18 +++++++++++++++ 6 files changed, 92 insertions(+) create mode 100644 src/postprocessors.rs create mode 100644 tests/testdata/expected/postprocessors/hard_linebreaks.md create mode 100644 tests/testdata/input/postprocessors/hard_linebreaks.md diff --git a/src/lib.rs b/src/lib.rs index f4b3fe7..fcf7ae0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ extern crate lazy_static; mod context; mod frontmatter; +pub mod postprocessors; mod references; mod walker; diff --git a/src/main.rs b/src/main.rs index 2f5f7c0..902783d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use eyre::{eyre, Result}; use gumdrop::Options; +use obsidian_export::postprocessors::softbreaks_to_hardbreaks; use obsidian_export::{ExportError, Exporter, FrontmatterStrategy, WalkOptions}; use std::{env, path::PathBuf}; @@ -46,6 +47,13 @@ struct Opts { #[options(no_short, help = "Don't process embeds recursively", default = "false")] no_recursive_embeds: bool, + + #[options( + no_short, + help = "Convert soft line breaks to hard line breaks. This mimics Obsidian's 'Strict line breaks' setting", + default = "false" + )] + hard_linebreaks: bool, } fn frontmatter_strategy_from_str(input: &str) -> Result { @@ -82,6 +90,10 @@ fn main() { exporter.process_embeds_recursively(!args.no_recursive_embeds); exporter.walk_options(walk_options); + if args.hard_linebreaks { + exporter.add_postprocessor(&softbreaks_to_hardbreaks); + } + if let Some(path) = args.start_at { exporter.start_at(path); } diff --git a/src/postprocessors.rs b/src/postprocessors.rs new file mode 100644 index 0000000..8c3fb3a --- /dev/null +++ b/src/postprocessors.rs @@ -0,0 +1,20 @@ +//! A collection of officially maintained [postprocessors][crate::Postprocessor]. + +use super::{Context, MarkdownEvents, PostprocessorResult}; +use pulldown_cmark::Event; + +/// This postprocessor converts all soft line breaks to hard line breaks. Enabling this mimics +/// Obsidian's _'Strict line breaks'_ setting. +pub fn softbreaks_to_hardbreaks( + context: Context, + events: MarkdownEvents, +) -> (Context, MarkdownEvents, PostprocessorResult) { + let events = events + .into_iter() + .map(|event| match event { + Event::SoftBreak => Event::HardBreak, + _ => event, + }) + .collect(); + (context, events, PostprocessorResult::Continue) +} diff --git a/tests/postprocessors_test.rs b/tests/postprocessors_test.rs index 10f1c8d..bc95318 100644 --- a/tests/postprocessors_test.rs +++ b/tests/postprocessors_test.rs @@ -1,3 +1,4 @@ +use obsidian_export::postprocessors::softbreaks_to_hardbreaks; use obsidian_export::{Context, Exporter, MarkdownEvents, PostprocessorResult}; use pretty_assertions::assert_eq; use pulldown_cmark::{CowStr, Event}; @@ -208,3 +209,25 @@ fn test_embed_postprocessors_context() { exporter.run().unwrap(); } + +#[test] +fn test_softbreaks_to_hardbreaks() { + 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(), + ); + exporter.add_postprocessor(&softbreaks_to_hardbreaks); + exporter.run().unwrap(); + + let expected = + read_to_string("tests/testdata/expected/postprocessors/hard_linebreaks.md").unwrap(); + let actual = read_to_string( + tmp_dir + .path() + .clone() + .join(PathBuf::from("hard_linebreaks.md")), + ) + .unwrap(); + assert_eq!(expected, actual); +} diff --git a/tests/testdata/expected/postprocessors/hard_linebreaks.md b/tests/testdata/expected/postprocessors/hard_linebreaks.md new file mode 100644 index 0000000..bc4f2c4 --- /dev/null +++ b/tests/testdata/expected/postprocessors/hard_linebreaks.md @@ -0,0 +1,18 @@ +# Heading 1 + +Here's a random quote from fortune(6): + +"I don't have to take this abuse from you -- I've got hundreds of +people waiting to abuse me." +-- Bill Murray, "Ghostbusters" + +## Heading 2 + +Here's another random quote from fortune(6): + +```` +Cinemuck, n.: + The combination of popcorn, soda, and melted chocolate which + covers the floors of movie theaters. + -- Rich Hall, "Sniglets" +```` diff --git a/tests/testdata/input/postprocessors/hard_linebreaks.md b/tests/testdata/input/postprocessors/hard_linebreaks.md new file mode 100644 index 0000000..ff69c63 --- /dev/null +++ b/tests/testdata/input/postprocessors/hard_linebreaks.md @@ -0,0 +1,18 @@ +# Heading 1 + +Here's a random quote from fortune(6): + +"I don't have to take this abuse from you -- I've got hundreds of +people waiting to abuse me." + -- Bill Murray, "Ghostbusters" + +## Heading 2 + +Here's another random quote from fortune(6): + +``` +Cinemuck, n.: + The combination of popcorn, soda, and melted chocolate which + covers the floors of movie theaters. + -- Rich Hall, "Sniglets" +```