Add option to not URL encode links (Angle Bracket Escaping)

This commit is contained in:
KV Le 2022-12-25 03:09:28 -08:00
parent 80130260e9
commit ec4fa7329f
2 changed files with 45 additions and 4 deletions

View File

@ -216,6 +216,15 @@ pub enum PostprocessorResult {
StopAndSkipNote,
}
#[derive(Debug, Clone, Copy)]
/// Way to encode links
pub enum LinkStrategy {
/// URL encode links
UrlEncoded,
/// Don't do anything to links
NoEncode,
}
#[derive(Clone)]
/// Exporter provides the main interface to this library.
///
@ -228,6 +237,7 @@ pub struct Exporter<'a> {
destination: PathBuf,
start_at: PathBuf,
frontmatter_strategy: FrontmatterStrategy,
link_strategy: LinkStrategy,
vault_contents: Option<Vec<PathBuf>>,
walk_options: WalkOptions<'a>,
process_embeds_recursively: bool,
@ -241,6 +251,7 @@ impl<'a> fmt::Debug for Exporter<'a> {
.field("root", &self.root)
.field("destination", &self.destination)
.field("frontmatter_strategy", &self.frontmatter_strategy)
.field("link_strategy", &self.link_strategy)
.field("vault_contents", &self.vault_contents)
.field("walk_options", &self.walk_options)
.field(
@ -271,6 +282,7 @@ impl<'a> Exporter<'a> {
root,
destination,
frontmatter_strategy: FrontmatterStrategy::Auto,
link_strategy: LinkStrategy::UrlEncoded,
walk_options: WalkOptions::default(),
process_embeds_recursively: true,
vault_contents: None,
@ -300,6 +312,12 @@ impl<'a> Exporter<'a> {
self
}
/// Set the [`LinkStrategy`] to be used for this exporter.
pub fn link_strategy(&mut self, strategy: LinkStrategy) -> &mut Exporter<'a> {
self.link_strategy = strategy;
self
}
/// Set the behavior when recursive embeds are encountered.
///
/// When `recursive` is true (the default), emdeds are always processed recursively. This may
@ -381,7 +399,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(())
@ -686,7 +704,12 @@ impl<'a> Exporter<'a> {
.expect("should be able to build relative path when target file is found in vault");
let rel_link = rel_link.to_string_lossy();
let mut link = utf8_percent_encode(&rel_link, PERCENTENCODE_CHARS).to_string();
let mut link = match self.link_strategy {
LinkStrategy::UrlEncoded => {
utf8_percent_encode(&rel_link, PERCENTENCODE_CHARS).to_string()
}
LinkStrategy::NoEncode => rel_link.to_string(), // pulldown_cmark automatically puts it into brackets
};
if let Some(section) = reference.section {
link.push('#');
@ -732,7 +755,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")
})
}

View File

@ -1,7 +1,7 @@
use eyre::{eyre, Result};
use gumdrop::Options;
use obsidian_export::postprocessors::softbreaks_to_hardbreaks;
use obsidian_export::{ExportError, Exporter, FrontmatterStrategy, WalkOptions};
use obsidian_export::{ExportError, Exporter, FrontmatterStrategy, LinkStrategy, WalkOptions};
use std::{env, path::PathBuf};
const VERSION: &str = env!("CARGO_PKG_VERSION");
@ -32,6 +32,15 @@ struct Opts {
)]
frontmatter_strategy: FrontmatterStrategy,
#[options(
help = "Link strategy (one of: encoded, none)",
no_short,
long = "link",
parse(try_from_str = "link_strategy_from_str"),
default = "encoded"
)]
link_strategy: LinkStrategy,
#[options(
no_short,
help = "Read ignore patterns from files with this name",
@ -65,6 +74,14 @@ fn frontmatter_strategy_from_str(input: &str) -> Result<FrontmatterStrategy> {
}
}
fn link_strategy_from_str(input: &str) -> Result<LinkStrategy> {
match input {
"encoded" => Ok(LinkStrategy::UrlEncoded),
"none" => Ok(LinkStrategy::NoEncode),
_ => Err(eyre!("must be one of: encoded, none")),
}
}
fn main() {
// Due to the use of free arguments in Opts, we must bypass Gumdrop to determine whether the
// version flag was specified. Without this, "missing required free argument" would get printed
@ -87,6 +104,7 @@ fn main() {
let mut exporter = Exporter::new(root, destination);
exporter.frontmatter_strategy(args.frontmatter_strategy);
exporter.link_strategy(args.link_strategy);
exporter.process_embeds_recursively(!args.no_recursive_embeds);
exporter.walk_options(walk_options);