subx_cli/core/formats/
styling.rs

1use regex::Regex;
2
3use crate::core::formats::StylingInfo;
4use crate::core::formats::converter::FormatConverter;
5
6impl FormatConverter {
7    /// 從 SRT 標籤擷取樣式資訊
8    pub(crate) fn extract_srt_styling(&self, text: &str) -> crate::Result<StylingInfo> {
9        let mut styling = StylingInfo::default();
10        if text.contains("<b>") || text.contains("<B>") {
11            styling.bold = true;
12        }
13        if text.contains("<i>") || text.contains("<I>") {
14            styling.italic = true;
15        }
16        if text.contains("<u>") || text.contains("<U>") {
17            styling.underline = true;
18        }
19        if let Some(color) = self.extract_color_from_tags(text) {
20            styling.color = Some(color);
21        }
22        Ok(styling)
23    }
24
25    /// 將 SRT 標籤轉換為 ASS 標籤
26    pub(crate) fn convert_srt_tags_to_ass(&self, text: &str) -> String {
27        let mut result = text.to_string();
28        result = result.replace("<b>", "{\\b1}").replace("</b>", "{\\b0}");
29        result = result.replace("<i>", "{\\i1}").replace("</i>", "{\\i0}");
30        result = result.replace("<u>", "{\\u1}").replace("</u>", "{\\u0}");
31        let color_regex = Regex::new(r#"<font color=\"([^\"]+)\">"#).unwrap();
32        result = color_regex
33            .replace_all(&result, |caps: &regex::Captures| {
34                let color = &caps[1];
35                format!("{{\\c&H{}&}}", self.convert_color_to_ass(color))
36            })
37            .to_string();
38        result = result.replace("</font>", "{\\c}");
39        result
40    }
41
42    /// 移除 ASS 標籤
43    pub(crate) fn strip_ass_tags(&self, text: &str) -> String {
44        let tag_regex = Regex::new(r"\{[^}]*\}").unwrap();
45        tag_regex.replace_all(text, "").to_string()
46    }
47
48    /// 將 ASS 標籤轉換為 SRT 標籤
49    pub(crate) fn convert_ass_tags_to_srt(&self, text: &str) -> String {
50        let mut result = text.to_string();
51        let bold_regex = Regex::new(r"\{\\b1\}([^\{]*)\{\\b0\}").unwrap();
52        result = bold_regex.replace_all(&result, "<b>$1</b>").to_string();
53        let italic_regex = Regex::new(r"\{\\i1\}([^\{]*)\{\\i0\}").unwrap();
54        result = italic_regex.replace_all(&result, "<i>$1</i>").to_string();
55        let underline_regex = Regex::new(r"\{\\u1\}([^\{]*)\{\\u0\}").unwrap();
56        result = underline_regex
57            .replace_all(&result, "<u>$1</u>")
58            .to_string();
59        result
60    }
61
62    /// 從標籤中擷取顏色(簡易實作)
63    pub(crate) fn extract_color_from_tags(&self, _text: &str) -> Option<String> {
64        None
65    }
66
67    /// 將顏色字串轉換為 ASS 顏色碼
68    pub(crate) fn convert_color_to_ass(&self, color: &str) -> String {
69        color.trim_start_matches('#').to_string()
70    }
71
72    /// 將 SRT 標籤轉換為 VTT 標籤(簡易實作)
73    pub(crate) fn convert_srt_tags_to_vtt(&self, text: &str) -> String {
74        text.to_string()
75    }
76    /// 將 VTT 標籤轉換為 SRT 標籤(簡易實作)
77    pub(crate) fn convert_vtt_tags_to_srt(&self, text: &str) -> String {
78        // VTT 使用類似 HTML 標籤,SRT 亦支援基本標籤,預設保留
79        text.to_string()
80    }
81    /// 移除 VTT 標籤(簡易實作)
82    pub(crate) fn strip_vtt_tags(&self, text: &str) -> String {
83        let tag_regex = Regex::new(r"</?[^>]+>").unwrap();
84        tag_regex.replace_all(text, "").to_string()
85    }
86}