use super::types::{ConversionOptions, FormatOptions};
use super::FormatConverter;
use crate::core::{EditorDocument, Result};
use ass_core::parser::ast::EventType;
#[cfg(not(feature = "std"))]
use alloc::{
format,
string::{String, ToString},
vec::Vec,
};
impl FormatConverter {
pub(super) fn export_webvtt(
document: &EditorDocument,
options: &ConversionOptions,
) -> Result<String> {
let mut output = String::new();
output.push_str("WEBVTT\n\n");
if let FormatOptions::WebVTT {
include_style_block: true,
..
} = &options.format_options
{
output.push_str("STYLE\n");
output.push_str("::cue {\n");
output
.push_str(" background-image: linear-gradient(to bottom, dimgray, lightgray);\n");
output.push_str(" color: papayawhip;\n");
output.push_str("}\n\n");
}
document.parse_script_with(|script| {
for section in script.sections() {
if let ass_core::parser::ast::Section::Events(events) = section {
for event in events {
if event.event_type == EventType::Dialogue {
let start = Self::ass_time_to_webvtt(event.start);
let end = Self::ass_time_to_webvtt(event.end);
output.push_str(&format!("{start} --> {end}"));
if let FormatOptions::WebVTT {
use_cue_settings: true,
..
} = &options.format_options
{
let margin_v: i32 = event.margin_v.parse().unwrap_or(0);
if margin_v != 0 {
output.push_str(&format!(" line:{}", 100 - margin_v));
}
}
output.push('\n');
let text = if options.strip_formatting {
Self::strip_ass_tags(event.text)
} else {
Self::convert_ass_to_webvtt_formatting(event.text)
};
output.push_str(&text.replace("\\N", "\n"));
output.push_str("\n\n");
}
}
}
}
})?;
Ok(output)
}
fn ass_time_to_webvtt(time: &str) -> String {
let parts: Vec<&str> = time.split(':').collect();
if parts.len() != 3 {
return time.to_string();
}
let hours = format!("{:02}", parts[0].parse::<u32>().unwrap_or(0));
let minutes = parts[1];
let seconds_parts: Vec<&str> = parts[2].split('.').collect();
let seconds = seconds_parts[0];
let centiseconds = seconds_parts.get(1).unwrap_or(&"00");
let millis = centiseconds.parse::<u32>().unwrap_or(0) * 10;
format!("{hours}:{minutes}:{seconds}.{millis:03}")
}
fn convert_ass_to_webvtt_formatting(text: &str) -> String {
let mut result = text.to_string();
result = result.replace("{\\i1}", "<i>");
result = result.replace("{\\i0}", "</i>");
result = result.replace("{\\b1}", "<b>");
result = result.replace("{\\b0}", "</b>");
result = result.replace("{\\u1}", "<u>");
result = result.replace("{\\u0}", "</u>");
while let Some(start) = result.find('{') {
if let Some(end) = result[start..].find('}') {
result.replace_range(start..start + end + 1, "");
} else {
break;
}
}
result
}
}