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.
This commit is contained in:
Nick Groenen 2022-01-02 00:42:51 +01:00
parent 838881fea0
commit 84308c9f1f
No known key found for this signature in database
GPG Key ID: 4F0AD019928AE098
6 changed files with 92 additions and 0 deletions

View File

@ -6,6 +6,7 @@ extern crate lazy_static;
mod context;
mod frontmatter;
pub mod postprocessors;
mod references;
mod walker;

View File

@ -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<FrontmatterStrategy> {
@ -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);
}

20
src/postprocessors.rs Normal file
View File

@ -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)
}

View File

@ -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);
}

View File

@ -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"
````

View File

@ -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"
```