Esempio n. 1
0
        /// <summary>
        /// Renders the specified parameters.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="renderCompleteHtmlPage">If set to <c>true</c>, render the complete HTML page.</param>
        /// <returns>
        /// The output of the rendering.
        /// </returns>
        public async Task <RenderedPassage> RenderAsync(RenderingParameters parameters, bool renderCompleteHtmlPage)
        {
            // Set up the rendered passage
            RenderedPassage renderedPassage = new RenderedPassage();

            // Get the first provider
            IProvider?firstProvider = this.Providers.FirstOrDefault(p => p.Id == parameters.PrimaryProvider);

            if (firstProvider == null)
            {
                return(renderedPassage);
            }

            // Get the first translation
            Chapter firstChapter = await firstProvider.GetChapterAsync(parameters.PrimaryTranslation, parameters.PassageReference.ChapterReference);

            // Setup the previous chapter reference
            if (firstChapter.PreviousChapterReference.IsValid)
            {
                renderedPassage.PreviousPassage = firstChapter.PreviousChapterReference.AsPassageReference();
            }
            else
            {
                renderedPassage.PreviousPassage = new PassageReference();
            }

            // Setup the next chapter reference
            if (firstChapter.NextChapterReference.IsValid)
            {
                renderedPassage.NextPassage = firstChapter.NextChapterReference.AsPassageReference();
            }
            else
            {
                renderedPassage.NextPassage = new PassageReference();
            }

            // Render appropriately
            if (parameters.Format == RenderFormat.Text)
            {
                // Strip italics
                if (this.Providers.FirstOrDefault(p => p.Id == parameters.PrimaryProvider)?.SupportsItalics ?? false)
                {
                    StringBuilder sb    = new StringBuilder();
                    string[]      lines = firstChapter.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string line in lines)
                    {
                        sb.AppendLine(line.StripItalics());
                    }

                    renderedPassage.Content = sb.ToString();
                }
                else
                {
                    // We cannot do interlinear in text mode
                    renderedPassage.Content = firstChapter.Text;
                }
            }
            else if (parameters.Format == RenderFormat.Accordance)
            {
                // Strip italics
                if (this.Providers.FirstOrDefault(p => p.Id == parameters.PrimaryProvider)?.SupportsItalics ?? false)
                {
                    StringBuilder sb    = new StringBuilder();
                    string[]      lines = firstChapter.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string line in lines)
                    {
                        sb.Append(parameters.PassageReference.ChapterReference);
                        sb.Append(':');
                        sb.AppendLine(line.RenderItalics("i").TrimStart());
                    }

                    renderedPassage.Content = sb.ToString();
                }
                else
                {
                    // We cannot do interlinear in text mode
                    renderedPassage.Content = firstChapter.Text;
                }
            }
            else
            {
                // Nuke the second translation, if it is the same
                if (parameters.PrimaryTranslation == parameters.SecondaryTranslation)
                {
                    parameters.SecondaryTranslation = string.Empty;
                }

                // If we have a second translation
                StringBuilder sb = new StringBuilder();
                if (renderCompleteHtmlPage)
                {
                    sb.AppendLine("<!DOCTYPE html>");
                    sb.AppendLine("<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />");
                    sb.AppendLine("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />");
                    sb.Append("<style>");
                    sb.Append(parameters.RenderCss());
                    sb.AppendLine("</style></head><body>");
                }

                if (!string.IsNullOrWhiteSpace(parameters.SecondaryTranslation))
                {
                    // Get the second provider
                    IProvider?secondProvider = this.Providers.FirstOrDefault(p => p.Id == (parameters.SecondaryProvider ?? parameters.PrimaryProvider));
                    if (secondProvider == null)
                    {
                        secondProvider = firstProvider;
                    }

                    // Get the second translation, if specified
                    Chapter secondChapter = await secondProvider.GetChapterAsync(parameters.SecondaryTranslation, parameters.PassageReference.ChapterReference);

                    // If the next chapter reference is invalid, see if this chapter has a valid reference
                    if (!renderedPassage.NextPassage.IsValid && secondChapter.NextChapterReference.IsValid)
                    {
                        renderedPassage.NextPassage = secondChapter.NextChapterReference.AsPassageReference();
                    }

                    // If the previous chapter reference is invalid, see if this chapter has a valid reference
                    if (!renderedPassage.PreviousPassage.IsValid && secondChapter.PreviousChapterReference.IsValid)
                    {
                        renderedPassage.PreviousPassage = secondChapter.PreviousChapterReference.AsPassageReference();
                    }

                    // Render both interlinear
                    bool          hasContent = false;
                    List <string> lines1     = firstChapter.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).ToList();
                    List <string> lines2     = secondChapter.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).ToList();

                    // Add any missing verses
                    for (int i = 0; i < lines1.Count; i++)
                    {
                        int expectedVerseNumber = i + 1;
                        if (int.TryParse(lines1[i].Substring(0, lines1[i].IndexOf(' ')), out int verseNumber) && verseNumber > expectedVerseNumber)
                        {
                            lines1.Insert(i, $"{expectedVerseNumber}  ");
                        }
                    }

                    for (int i = 0; i < lines2.Count; i++)
                    {
                        int expectedVerseNumber = i + 1;
                        if (int.TryParse(lines2[i].Substring(0, lines2[i].IndexOf(' ')), out int verseNumber) && verseNumber > expectedVerseNumber)
                        {
                            lines2.Insert(i, $"{expectedVerseNumber}  ");
                        }
                    }

                    // Render each line
                    for (int i = 0; i < lines1.Count; i++)
                    {
                        hasContent = true;
                        if (i < lines2.Count)
                        {
                            RenderedVerse firstAttempt  = this.RenderInterlinearLinesAsHtml(lines1[i], lines2[i], parameters, false);
                            RenderedVerse secondAttempt = this.RenderInterlinearLinesAsHtml(lines1[i], lines2[i], parameters, true);

                            // If there are no words in any, skip
                            if (firstAttempt.TotalWordsLine1 == 0 && firstAttempt.TotalWordsLine2 == 0 && firstAttempt.DivergentPhrases == 0 && firstAttempt.WordsInCommon == 0 &&
                                secondAttempt.TotalWordsLine1 == 0 && secondAttempt.TotalWordsLine2 == 0 && secondAttempt.DivergentPhrases == 0 && secondAttempt.WordsInCommon == 0)
                            {
                                continue;
                            }

                            // Calculate which rendering to use, based on verse statistics
                            bool useFirstAttempt;
                            if (firstAttempt.WordsInCommon == secondAttempt.WordsInCommon)
                            {
                                // Use the number of divergent phrases, as both have the same number of words in common
                                useFirstAttempt = firstAttempt.DivergentPhrases > secondAttempt.DivergentPhrases;
                            }
                            else
                            {
                                useFirstAttempt = firstAttempt.WordsInCommon > secondAttempt.WordsInCommon;
                            }

                            if (parameters.IsDebug)
                            {
                                // Display debugging information for the renderer
                                // This does not have to be user-friendly output
                                if (i > 0)
                                {
                                    sb.Append("<hr style=\"padding:0;border:none;width:100%;height:1px;color:#000;background-color:#000\">");
                                }

                                // Build the verse statistics output
                                string verseStatistics1 = $" <span style=\"font-family:consolas,courier\">[DivergentPhrases={firstAttempt.DivergentPhrases},TotalWordsLine1={firstAttempt.TotalWordsLine1},TotalWordsLine2={firstAttempt.TotalWordsLine2},WordsInCommon={firstAttempt.WordsInCommon}]</span><br>";
                                string verseStatistics2 = $" <span style=\"font-family:consolas,courier\">[DivergentPhrases={secondAttempt.DivergentPhrases},TotalWordsLine1={secondAttempt.TotalWordsLine1},TotalWordsLine2={secondAttempt.TotalWordsLine2},WordsInCommon={secondAttempt.WordsInCommon}]</span><br>";

                                string bestNote = " title=\"This is the method selected as the best by the renderer\"";
                                if (useFirstAttempt)
                                {
                                    sb.Append($"<strong style=\"font-family:consolas,courier\"{bestNote}>Reverse Scan*</strong>{verseStatistics1} {firstAttempt.Content}");
                                    sb.Append($"<strong style=\"font-family:consolas,courier\">Forward Scan&nbsp;</strong>{verseStatistics2} {secondAttempt.Content}");
                                }
                                else
                                {
                                    sb.Append($"<strong style=\"font-family:consolas,courier\"{bestNote}>Reverse Scan&nbsp;</strong>{verseStatistics1} {firstAttempt.Content}");
                                    sb.Append($"<strong style=\"font-family:consolas,courier\"{bestNote}>Forward Scan*</strong>{verseStatistics2} {secondAttempt.Content}");
                                }
                            }
                            else if (useFirstAttempt)
                            {
                                sb.Append(firstAttempt.Content);
                            }
                            else
                            {
                                sb.Append(secondAttempt.Content);
                            }
                        }
                        else
                        {
                            sb.Append(this.RenderInterlinearLinesAsHtml(lines1[i], string.Empty, parameters, false).Content);
                        }
                    }

                    // If lines 2 was longer, add its remaining entries
                    if (lines2.Count > lines1.Count)
                    {
                        sb.AppendLine("</head><body>");
                        for (int i = lines1.Count; i < lines2.Count; i++)
                        {
                            sb.Append(this.RenderInterlinearLinesAsHtml(string.Empty, lines2[i], parameters, false).Content);
                        }
                    }

                    // Make sure we have some content
                    if (hasContent)
                    {
                        // Get all of the translations
                        List <Translation> translations = new List <Translation>();
                        await foreach (Translation translation in firstProvider.GetTranslationsAsync())
                        {
                            translations.Add(translation);
                        }

                        if (secondProvider.Id != firstProvider.Id)
                        {
                            await foreach (Translation translation in secondProvider.GetTranslationsAsync())
                            {
                                translations.Add(translation);
                            }
                        }

                        // Fix up the tooltips
                        Translation?primaryTranslation       = translations.FirstOrDefault(t => t.Code == parameters.PrimaryTranslation);
                        string      primaryTranslationName   = primaryTranslation?.UniqueName(translations) ?? "Primary Translation";
                        Translation?secondaryTranslation     = translations.FirstOrDefault(t => t.Code == parameters.SecondaryTranslation);
                        string      secondaryTranslationName = secondaryTranslation?.UniqueName(translations) ?? "Secondary Translation";
                        sb.Replace($"<span title=\"{parameters.PrimaryTranslation}\">", $"<span title=\"{primaryTranslationName}\">");
                        sb.Replace($"<span title=\"{parameters.SecondaryTranslation}\">", $"<span title=\"{secondaryTranslationName}\">");

                        // Supplement the translation copyrights if the chapter copyrights are missing
                        if (string.IsNullOrWhiteSpace(firstChapter.Copyright) && !string.IsNullOrWhiteSpace(primaryTranslation?.Copyright))
                        {
                            firstChapter.Copyright = primaryTranslation.Copyright;
                        }

                        if (string.IsNullOrWhiteSpace(secondChapter.Copyright) && !string.IsNullOrWhiteSpace(secondaryTranslation?.Copyright))
                        {
                            secondChapter.Copyright = secondaryTranslation.Copyright;
                        }

                        // Display copyright
                        if (!string.IsNullOrWhiteSpace(firstChapter.Copyright) || !string.IsNullOrWhiteSpace(secondChapter.Copyright))
                        {
                            sb.Append("<p class=\"copyright\">");
                            if (!string.IsNullOrWhiteSpace(firstChapter.Copyright))
                            {
                                sb.Append($"<strong>{primaryTranslationName}: </strong> {firstChapter.Copyright}");
                            }

                            if (!string.IsNullOrWhiteSpace(firstChapter.Copyright) && !string.IsNullOrWhiteSpace(secondChapter.Copyright))
                            {
                                sb.Append("<br>");
                            }

                            if (!string.IsNullOrWhiteSpace(secondChapter.Copyright))
                            {
                                sb.Append($"<strong>{secondaryTranslationName}: </strong> {secondChapter.Copyright}");
                            }

                            sb.AppendLine("</p>");
                        }
                    }
                }
                else
                {
                    // Just render the first translation
                    foreach (string line in firstChapter.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        sb.Append(this.RenderLineAsHtml(line, parameters));
                    }

                    // Display copyright
                    if (!string.IsNullOrWhiteSpace(firstChapter.Copyright))
                    {
                        sb.AppendLine($"<p class=\"copyright\">{firstChapter.Copyright}</p>");
                    }
                }

                if (renderCompleteHtmlPage)
                {
                    // End the document
                    sb.AppendLine("</body></html>");
                }

                renderedPassage.Content = sb.ToString();
            }

            // Return the rendered passage
            return(renderedPassage);
        }