diff --git a/Cargo.toml b/Cargo.toml
index f84d846..7531292 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,9 +3,15 @@ name = "nethys-to-obsidian"
version = "0.1.0"
edition = "2024"
+[lib]
+crate-type = ["cdylib", "rlib"]
+
[dependencies]
anyhow = "1.0.102"
clap = { version = "4.6.1", features = ["derive", "env"] }
regex = "1.12.3"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
+
+# [target.'cfg(target_arch = "wasm32")'.dependencies]
+# wasm-bindgen = "0.2.121"
diff --git a/src/character.rs b/src/creature.rs
similarity index 85%
rename from src/character.rs
rename to src/creature.rs
index ba4f8aa..1973915 100644
--- a/src/character.rs
+++ b/src/creature.rs
@@ -1,5 +1,8 @@
use std::{fmt::Write as _, sync::LazyLock};
+// #[cfg(target_arch = "wasm32")]
+// use wasm_bindgen::prelude::wasm_bindgen;
+
use regex::Regex;
use serde::Deserialize;
@@ -52,16 +55,31 @@ fn fix_action_icons(input: String) -> String {
.replace(r#""#, "`[reaction]`")
}
+fn fix_html(s: String) -> String {
+ let html_tags_re = Regex::new(r"<[^<>]*>").unwrap();
+
+ let s = fix_action_icons(s);
+ let s = s.replace("
", "\n");
+ let s = html_tags_re.replace_all(&s, "");
+
+ s.to_string()
+}
+
+fn split_sections(s: &str) -> Vec {
+ let s = fix_html(s.to_string());
+ let re_split = Regex::new(r"\r?\n\s*\r?\n").unwrap();
+ re_split.split(&s).map(String::from).collect()
+}
+
fn parse_ability_section(
markdown: &str,
mut section_start: impl FnMut(&str) -> bool,
mut section_end: impl FnMut(&str) -> bool,
) -> String {
- let re_split = Regex::new(r"\n\s*\n").unwrap();
- let sections: Vec<&str> = re_split.split(markdown).collect();
+ let sections = split_sections(markdown);
let relevant_sections = sections
- .into_iter()
+ .iter()
.map(|s| s.trim_start())
.filter(|s| s.starts_with("**"))
.skip_while(|s| !section_start(s))
@@ -82,11 +100,10 @@ fn parse_offensive_abilities(markdown: &str) -> String {
}
fn parse_defensive_abilities(markdown: &str) -> String {
- let re_split = Regex::new(r"\n\s*\n").unwrap();
- let sections: Vec<&str> = re_split.split(markdown).collect();
+ let sections = split_sections(markdown);
let relevant_sections = sections
- .into_iter()
+ .iter()
.map(|s| s.trim_start())
.filter(|s| s.starts_with("**"))
.skip_while(|s| !s.starts_with("**HP**"))
@@ -123,6 +140,16 @@ fn plussed(number: i32) -> String {
}
}
+// #[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
+pub fn find_creature_to_obsidian(name: &str) -> Option {
+ let mut candidates: Vec<&Creature> = CREATURES.iter().filter(|c| &c.name == &name).collect();
+ candidates.sort_unstable_by_key(|&creature| creature.legacy_id.is_none());
+
+ let &creature = candidates.first()?;
+
+ Some(creature_to_obsidian(creature))
+}
+
pub fn creature_to_obsidian(sb: &Creature) -> String {
let traits_str = sb
.traits
diff --git a/src/lib.rs b/src/lib.rs
index 7889122..f5193eb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1 +1 @@
-pub mod character;
+pub mod creature;
diff --git a/src/main.rs b/src/main.rs
index c817edf..850ef94 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,6 @@
use anyhow::anyhow;
use clap::{Parser, Subcommand};
-use nethys_to_obsidian::character::{CREATURES, Creature, creature_to_obsidian};
+use nethys_to_obsidian::creature::find_creature_to_obsidian;
/// Convert statblocks from Archives of Nethys into markdownish-blocks compatible with pf2e-stats obsidian plugin.
#[derive(Parser, Debug)]
@@ -19,14 +19,9 @@ fn main() -> anyhow::Result<()> {
let args = Args::parse();
let Command::Creature { name } = args.command;
- let mut candidates: Vec<&Creature> = CREATURES.iter().filter(|c| &c.name == &name).collect();
+ let creature = find_creature_to_obsidian(&name).ok_or(anyhow!("No creature with that name"))?;
- candidates.sort_unstable_by_key(|&creature| creature.legacy_id.is_none());
- let &creature = candidates
- .first()
- .ok_or(anyhow!("No creature with that name"))?;
-
- print!("{}", creature_to_obsidian(creature));
+ print!("{creature}");
Ok(())
}