ivandrofly

SubtitleEdit: FixInvalidItalicTags

Jan 2nd, 2025
13
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 17.78 KB | None | 0 0
  1. public static string FixInvalidItalicTags(string input)
  2.         {
  3.             var text = input;
  4.  
  5.             var preTags = string.Empty;
  6.             if (text.StartsWith("{\\", StringComparison.Ordinal))
  7.             {
  8.                 var endIdx = text.IndexOf('}', 2);
  9.                 if (endIdx > 2)
  10.                 {
  11.                     preTags = text.Substring(0, endIdx + 1);
  12.                     text = text.Remove(0, endIdx + 1);
  13.                 }
  14.             }
  15.  
  16.             const string beginTag = "<i>";
  17.             const string endTag = "</i>";
  18.             foreach (var beginTagVariation in BeginTagVariations)
  19.             {
  20.                 text = text.Replace(beginTagVariation, beginTag);
  21.             }
  22.  
  23.             foreach (var endTagVariation in EndTagVariations)
  24.             {
  25.                 text = text.Replace(endTagVariation, endTag);
  26.             }
  27.  
  28.             text = text.Replace("</i> <i>", "_@_");
  29.             text = text.Replace(" _@_", "_@_");
  30.             text = text.Replace(" _@_ ", "_@_");
  31.             text = text.Replace("_@_", " ");
  32.  
  33.             var tagsToCheck = new HashSet<string>(text.Length / 3);
  34.  
  35.             var l = 0;
  36.             for (var r = 0; r < text.Length; r++)
  37.             {
  38.                 if (text[r] == '<')
  39.                 {
  40.                     l = r;
  41.                 }
  42.                 else if (text[r] == '>' && text[l] == '<') // expecting: <i/>
  43.                 {
  44.                     if (text[r - 1] == '/')
  45.                     {
  46.                         tagsToCheck.Add(text.Substring(l, r - l + 1));
  47.                     }
  48.                     else
  49.                     {
  50.                         l = r + 1;
  51.                     }
  52.                 }
  53.                 else if (text[l] != '<')
  54.                 {
  55.                     l = r;
  56.                 }
  57.             }
  58.  
  59.             foreach (string tag in tagsToCheck)
  60.             {
  61.                 var hasOpeningVariant = text.Contains(tag.Replace("/", string.Empty));
  62.  
  63.                 if (hasOpeningVariant)
  64.                 {
  65.                     text = text.Replace(tag, tag
  66.                         .Replace("/", string.Empty)
  67.                         .Replace("<", "</"));
  68.                 }
  69.                 else // remove
  70.                 {
  71.                     text = text.Replace(tag, string.Empty);
  72.                 }
  73.             }
  74.  
  75.             var replacement = text.Contains(beginTag) ? endTag : string.Empty;
  76.             foreach (var invalidTag in new[] { "<i/>", "<I/>" })
  77.             {
  78.                 text = text.Replace(invalidTag, replacement);
  79.             }
  80.  
  81.             text = text.Replace("]<i> ", "] <i>");
  82.             text = text.Replace(")<i> ", ") <i>");
  83.             text = text.Replace("] </i>", "] </i>");
  84.             text = text.Replace(") </i>", ") </i>");
  85.  
  86.             text = text.Replace(beginTag + beginTag, beginTag);
  87.             text = text.Replace(endTag + endTag, endTag);
  88.  
  89.             var italicBeginTagCount = Utilities.CountTagInText(text, beginTag);
  90.             var italicEndTagCount = Utilities.CountTagInText(text, endTag);
  91.             var noOfLines = Utilities.GetNumberOfLines(text);
  92.             if (italicBeginTagCount + italicEndTagCount == 0)
  93.             {
  94.                 return preTags + text;
  95.             }
  96.  
  97.             if (italicBeginTagCount == 1 && italicEndTagCount == 1 && text.IndexOf(beginTag, StringComparison.Ordinal) > text.IndexOf(endTag, StringComparison.Ordinal))
  98.             {
  99.                 const string pattern = "___________@";
  100.                 text = text.Replace(beginTag, pattern);
  101.                 text = text.Replace(endTag, beginTag);
  102.                 text = text.Replace(pattern, endTag);
  103.             }
  104.  
  105.             if (italicBeginTagCount == 2 && italicEndTagCount == 0)
  106.             {
  107.                 var firstIndex = text.IndexOf(beginTag, StringComparison.Ordinal);
  108.                 var lastIndex = text.LastIndexOf(beginTag, StringComparison.Ordinal);
  109.                 var lastIndexWithNewLine = text.LastIndexOf(Environment.NewLine + beginTag, StringComparison.Ordinal) + Environment.NewLine.Length;
  110.                 if (noOfLines == 2 && lastIndex == lastIndexWithNewLine && firstIndex < 2)
  111.                 {
  112.                     text = text.Replace(Environment.NewLine, endTag + Environment.NewLine) + endTag;
  113.                 }
  114.                 else
  115.                 {
  116.                     text = text.Remove(lastIndex, beginTag.Length).Insert(lastIndex, endTag);
  117.                 }
  118.             }
  119.  
  120.             if (italicBeginTagCount == 1 && italicEndTagCount == 2)
  121.             {
  122.                 var firstIndex = text.IndexOf(endTag, StringComparison.Ordinal);
  123.                 if (text.StartsWith("</i>-<i>-", StringComparison.Ordinal) ||
  124.                     text.StartsWith("</i>- <i>-", StringComparison.Ordinal) ||
  125.                     text.StartsWith("</i>- <i> -", StringComparison.Ordinal) ||
  126.                     text.StartsWith("</i>-<i> -", StringComparison.Ordinal))
  127.                 {
  128.                     text = text.Remove(0, 5);
  129.                 }
  130.                 else if (firstIndex == 0)
  131.                 {
  132.                     text = text.Remove(0, 4);
  133.                 }
  134.                 else
  135.                 {
  136.                     text = text.Substring(0, firstIndex) + text.Substring(firstIndex + endTag.Length);
  137.                 }
  138.             }
  139.  
  140.             if (italicBeginTagCount == 2 && italicEndTagCount == 1)
  141.             {
  142.                 var lines = text.SplitToLines();
  143.                 if (lines.Count == 2 && lines[0].StartsWith(beginTag, StringComparison.Ordinal) && lines[0].EndsWith(endTag, StringComparison.Ordinal) &&
  144.                     lines[1].StartsWith(beginTag, StringComparison.Ordinal))
  145.                 {
  146.                     text = text.TrimEnd() + endTag;
  147.                 }
  148.                 else
  149.                 {
  150.                     var lastIndex = text.LastIndexOf(beginTag, StringComparison.Ordinal);
  151.                     if (text.Length > lastIndex + endTag.Length)
  152.                     {
  153.                         text = text.Substring(0, lastIndex) + text.Substring(lastIndex - 1 + endTag.Length);
  154.                     }
  155.                     else
  156.                     {
  157.                         text = text.Substring(0, lastIndex - 1) + endTag;
  158.                     }
  159.                 }
  160.                 if (text.StartsWith(beginTag, StringComparison.Ordinal) && text.EndsWith(endTag, StringComparison.Ordinal) && text.Contains(endTag + Environment.NewLine + beginTag))
  161.                 {
  162.                     text = text.Replace(endTag + Environment.NewLine + beginTag, Environment.NewLine);
  163.                 }
  164.             }
  165.  
  166.             if (italicBeginTagCount == 1 && italicEndTagCount == 0)
  167.             {
  168.                 var lines = text.SplitToLines();
  169.                 var sc = StringComparison.Ordinal;
  170.                 for (int i = 0; i < lines.Count; i++)
  171.                 {
  172.                     var line = lines[i];
  173.                     var italicIndex = line.LastIndexOf(beginTag, StringComparison.Ordinal);
  174.                    
  175.                     // no italic in current 'i' line, try next
  176.                     if (italicIndex < 0)
  177.                     {
  178.                         continue;
  179.                     }
  180.  
  181.                     // try earlier insert if possible e.g: <b><i>foobar</b> => <b><i>foobar</i></b>
  182.                     lines[i] = IsTextFormattable(line.Substring(italicIndex + 3))
  183.                         ? line.Insert(CalculateEarlyInsertIndex(line), endTag)
  184.                         : line.Replace(beginTag, string.Empty);
  185.  
  186.                     break; // break as soon as we reach here since italicBeginTagCount == 1
  187.  
  188.                     int CalculateEarlyInsertIndex(string s)
  189.                     {
  190.                         var len = s.Length;
  191.                         var lastClosingTagIndex = s.LastIndexOf("</", len - 1, len - italicIndex - 3, sc);
  192.                         while (lastClosingTagIndex > italicIndex + 3)
  193.                         {
  194.                             var tempClosingIdx = s.LastIndexOf("</", lastClosingTagIndex, lastClosingTagIndex - italicIndex - 3, sc);
  195.                             if (tempClosingIdx < 0) break;
  196.                             lastClosingTagIndex = tempClosingIdx;
  197.                         }
  198.                         // try finding the first closing tag index and insert the new closing there
  199.                         // to avoid having text with closed tags like <b><i>foo</b></i>
  200.                         return lastClosingTagIndex > italicIndex ? lastClosingTagIndex : len;
  201.                     }
  202.                 }
  203.                
  204.                 // reconstruct the text from lines
  205.                 text = string.Join(Environment.NewLine, lines);
  206.             }
  207.  
  208.             if (italicBeginTagCount == 0 && italicEndTagCount == 1)
  209.             {
  210.                 var cleanText = RemoveOpenCloseTags(text, TagItalic, TagBold, TagUnderline, TagCyrillicI);
  211.                 var isFixed = false;
  212.  
  213.                 // Foo.</i>
  214.                 if (text.EndsWith(endTag, StringComparison.Ordinal) && !cleanText.StartsWith('-') && !cleanText.Contains(Environment.NewLine + "-"))
  215.                 {
  216.                     text = beginTag + text;
  217.                     isFixed = true;
  218.                 }
  219.  
  220.                 // - Foo</i> | - Foo.
  221.                 // - Bar.    | - Foo.</i>
  222.                 if (!isFixed && Utilities.GetNumberOfLines(cleanText) == 2)
  223.                 {
  224.                     var newLineIndex = text.IndexOf(Environment.NewLine, StringComparison.Ordinal);
  225.                     if (newLineIndex > 0)
  226.                     {
  227.                         var firstLine = text.Substring(0, newLineIndex).Trim();
  228.                         var secondLine = text.Substring(newLineIndex + 2).Trim();
  229.                         if (firstLine.EndsWith(endTag, StringComparison.Ordinal))
  230.                         {
  231.                             firstLine = beginTag + firstLine;
  232.                             isFixed = true;
  233.                         }
  234.                         if (secondLine.EndsWith(endTag, StringComparison.Ordinal))
  235.                         {
  236.                             secondLine = beginTag + secondLine;
  237.                             isFixed = true;
  238.                         }
  239.                         text = firstLine + Environment.NewLine + secondLine;
  240.                     }
  241.                 }
  242.                 if (!isFixed)
  243.                 {
  244.                     text = text.Replace(endTag, string.Empty);
  245.                 }
  246.             }
  247.  
  248.             // - foo.</i>
  249.             // - bar.</i>
  250.             if (italicBeginTagCount == 0 && italicEndTagCount == 2 && text.Contains(endTag + Environment.NewLine, StringComparison.Ordinal) && text.EndsWith(endTag, StringComparison.Ordinal))
  251.             {
  252.                 text = text.Replace(endTag, string.Empty);
  253.                 text = beginTag + text + endTag;
  254.             }
  255.  
  256.             if (italicBeginTagCount == 0 && italicEndTagCount == 2)
  257.             {
  258.                 var firstIndex = text.IndexOf(endTag, StringComparison.Ordinal);
  259.                 text = text.Remove(firstIndex, endTag.Length).Insert(firstIndex, beginTag);
  260.             }
  261.  
  262.             // <i>Foo</i>
  263.             // <i>Bar</i>
  264.             if (italicBeginTagCount == 2 && italicEndTagCount == 2 && noOfLines == 2)
  265.             {
  266.                 var index = text.IndexOf(Environment.NewLine, StringComparison.Ordinal);
  267.                 if (index > 0 && text.Length > index + (beginTag.Length + endTag.Length))
  268.                 {
  269.                     var firstLine = text.Substring(0, index).Trim();
  270.                     var secondLine = text.Substring(index + Environment.NewLine.Length).Trim();
  271.  
  272.                     if (firstLine.Length > 10 && firstLine.StartsWith("- <i>", StringComparison.Ordinal) && firstLine.EndsWith(endTag, StringComparison.Ordinal))
  273.                     {
  274.                         text = "<i>- " + firstLine.Remove(0, 5) + Environment.NewLine + secondLine;
  275.                         text = text.Replace("<i>-  ", "<i>- ");
  276.                         index = text.IndexOf(Environment.NewLine, StringComparison.Ordinal);
  277.                         firstLine = text.Substring(0, index).Trim();
  278.                         secondLine = text.Substring(index + Environment.NewLine.Length).Trim();
  279.                     }
  280.                     if (secondLine.Length > 10 && secondLine.StartsWith("- <i>", StringComparison.Ordinal) && secondLine.EndsWith(endTag, StringComparison.Ordinal))
  281.                     {
  282.                         text = firstLine + Environment.NewLine + "<i>- " + secondLine.Remove(0, 5);
  283.                         text = text.Replace("<i>-  ", "<i>- ");
  284.                         index = text.IndexOf(Environment.NewLine, StringComparison.Ordinal);
  285.                         firstLine = text.Substring(0, index).Trim();
  286.                         secondLine = text.Substring(index + Environment.NewLine.Length).Trim();
  287.                     }
  288.  
  289.                     if (Utilities.StartsAndEndsWithTag(firstLine, beginTag, endTag) && Utilities.StartsAndEndsWithTag(secondLine, beginTag, endTag))
  290.                     {
  291.                         text = text.Replace(beginTag, string.Empty).Replace(endTag, string.Empty).Trim();
  292.                         text = beginTag + text + endTag;
  293.                     }
  294.                 }
  295.  
  296.                 //FALCONE:<i> I didn't think</i><br /><i>it was going to be you,</i>
  297.                 var colIdx = text.IndexOf(':');
  298.                 if (colIdx >= 0 && Utilities.CountTagInText(text, beginTag) + Utilities.CountTagInText(text, endTag) == 4 && text.Length > colIdx + 1 && !char.IsDigit(text[colIdx + 1]))
  299.                 {
  300.                     var firstLine = text.Substring(0, index);
  301.                     var secondLine = text.Substring(index).TrimStart();
  302.  
  303.                     var secIdxCol = secondLine.IndexOf(':');
  304.                     if (secIdxCol < 0 || !Utilities.IsBetweenNumbers(secondLine, secIdxCol))
  305.                     {
  306.                         var idx = firstLine.IndexOf(':');
  307.                         if (idx > 1)
  308.                         {
  309.                             var pre = text.Substring(0, idx + 1).TrimStart();
  310.                             var tempText = text.Remove(0, idx + 1);
  311.                            
  312.                             if (!tempText.StartsWith(']') && !tempText.StartsWith(')'))
  313.                             {
  314.                                 text = tempText;
  315.                                 text = FixInvalidItalicTags(text).Trim();
  316.                                 if (text.StartsWith("<i> ", StringComparison.OrdinalIgnoreCase))
  317.                                 {
  318.                                     text = Utilities.RemoveSpaceBeforeAfterTag(text, beginTag);
  319.                                 }
  320.  
  321.                                 text = pre + " " + text;
  322.                             }
  323.                         }
  324.                     }
  325.                 }
  326.             }
  327.  
  328.             //<i>- You think they're they gone?<i>
  329.             //<i>- That can't be.</i>
  330.             if (italicBeginTagCount == 3 && italicEndTagCount == 1 && noOfLines == 2)
  331.             {
  332.                 var newLineIdx = text.IndexOf(Environment.NewLine, StringComparison.Ordinal);
  333.                 var firstLine = text.Substring(0, newLineIdx).Trim();
  334.                 var secondLine = text.Substring(newLineIdx).Trim();
  335.  
  336.                 if ((Utilities.StartsAndEndsWithTag(firstLine, beginTag, beginTag) && Utilities.StartsAndEndsWithTag(secondLine, beginTag, endTag)) ||
  337.                     (Utilities.StartsAndEndsWithTag(secondLine, beginTag, beginTag) && Utilities.StartsAndEndsWithTag(firstLine, beginTag, endTag)))
  338.                 {
  339.                     text = text.Replace(beginTag, string.Empty);
  340.                     text = text.Replace(endTag, string.Empty);
  341.                     text = text.Replace("  ", " ").Trim();
  342.                     text = beginTag + text + endTag;
  343.                 }
  344.             }
  345.  
  346.             if (noOfLines == 3)
  347.             {
  348.                 var lines = text.SplitToLines();
  349.                 if ((italicBeginTagCount == 3 && italicEndTagCount == 2) || (italicBeginTagCount == 2 && italicEndTagCount == 3))
  350.                 {
  351.                     var numberOfItalics = 0;
  352.                     foreach (var line in lines)
  353.                     {
  354.                         if (line.StartsWith(beginTag, StringComparison.Ordinal))
  355.                         {
  356.                             numberOfItalics++;
  357.                         }
  358.  
  359.                         if (line.EndsWith(endTag, StringComparison.Ordinal))
  360.                         {
  361.                             numberOfItalics++;
  362.                         }
  363.                     }
  364.                     if (numberOfItalics == 5)
  365.                     { // fix missing tag
  366.                         text = "<i>" + text.Replace("<i>", string.Empty).Replace("</i>", string.Empty) + "</i>";
  367.                     }
  368.                 }
  369.             }
  370.  
  371.             text = text.Replace("<i></i>", string.Empty);
  372.             text = text.Replace("</i><i>", string.Empty);
  373.             if (text.IndexOf('@') < 0)
  374.             {
  375.                 text = text.Replace("</i> <i>", "@");
  376.                 text = text.Replace("<i> </i>", "@");
  377.                 text = text.Replace("<i>  </i>", "@");
  378.                 text = text.Replace("@ ", " ");
  379.                 text = text.Replace("@ ", " ");
  380.                 text = text.Replace(" @", " ");
  381.                 text = text.Replace(" @", " ");
  382.                 text = text.Replace("@", " ");
  383.             }
  384.             else
  385.             {
  386.                 text = text.Replace("</i> <i>", " ");
  387.                 text = text.Replace("<i> </i>", " ");
  388.                 text = text.Replace("<i>  </i>", " ");
  389.                 text = text.Replace("  ", " ");
  390.                 text = text.Replace("  ", " ");
  391.             }
  392.  
  393.             return preTags + text;
  394.         }
Add Comment
Please, Sign In to add comment