pub mod datatypes;
pub mod record;
pub mod group;
pub mod plugin;
pub mod subrecord;
pub mod string_types;
pub mod string_file;
pub mod utils;
pub mod special_records;
pub mod io;
pub mod editor;
pub mod localized_context;
pub mod plugin_loader;
pub mod bsa;
pub mod string_routes;
pub mod fast_extract;
#[cfg(debug_assertions)]
pub mod debug;
pub use plugin::{Plugin, PluginStats};
pub use record::Record;
pub use group::{Group, GroupChild, GroupType};
pub use subrecord::Subrecord;
pub use string_types::ExtractedString;
pub use string_file::{StringFile, StringFileType, StringEntry, StringFileSet, StringFileStats};
pub use datatypes::{RecordFlags, RawString};
pub use utils::{is_valid_string, EspError};
pub use special_records::SpecialRecordHandler;
pub use io::{
EspReader, EspWriter, StringFileReader, StringFileWriter, RawEspData,
DefaultEspReader, DefaultEspWriter,
};
pub use editor::{PluginEditor, TranslationDelta, RecordChange, RecordId};
pub use localized_context::LocalizedPluginContext;
pub use plugin_loader::LoadedPlugin;
pub use string_routes::{StringRouter, DefaultStringRouter};
#[cfg(debug_assertions)]
pub use debug::EspDebugger;
pub const SUPPORTED_EXTENSIONS: &[&str] = &["esp", "esm", "esl"];
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
#[allow(deprecated)]
pub fn extract_strings_from_file(file_path: std::path::PathBuf) -> std::result::Result<Vec<ExtractedString>, Box<dyn std::error::Error>> {
let language = "english";
if std::env::var("ESP_EXTRACTOR_USE_LEGACY_EXTRACT").ok().as_deref() == Some("1") {
let loaded = LoadedPlugin::load_auto(file_path, Some(language))?;
Ok(loaded.extract_strings())
} else {
Ok(fast_extract::extract_strings_fast(file_path.as_ref(), language)?)
}
}
pub fn extract_strings_from_file_fast(
file_path: std::path::PathBuf,
language: Option<&str>,
) -> std::result::Result<Vec<ExtractedString>, Box<dyn std::error::Error>> {
let language = language.unwrap_or("english");
Ok(fast_extract::extract_strings_fast(file_path.as_ref(), language)?)
}
pub fn apply_translations_to_file(
input_path: std::path::PathBuf,
output_path: std::path::PathBuf,
translations: Vec<ExtractedString>
) -> std::result::Result<(), Box<dyn std::error::Error>> {
Plugin::apply_translations(input_path, output_path, translations, None) }
pub fn is_supported_file(file_path: &std::path::Path) -> bool {
if !file_path.exists() {
return false;
}
let extension = file_path.extension()
.and_then(|ext| ext.to_str())
.map(|ext| ext.to_lowercase());
SUPPORTED_EXTENSIONS.iter().any(|&ext| Some(ext) == extension.as_deref())
}
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_supported_extensions() {
assert!(SUPPORTED_EXTENSIONS.contains(&"esp"));
assert!(SUPPORTED_EXTENSIONS.contains(&"esm"));
assert!(SUPPORTED_EXTENSIONS.contains(&"esl"));
}
#[test]
#[allow(clippy::const_is_empty)]
fn test_version_exists() {
assert!(!VERSION.is_empty());
}
}