Пример #1
0
        public void Add_Tags_Correctly()
        {
            var tagMethod = new TagMethod();
            var dbg       = new DebugEngineProxyBuilder();

            tagMethod.TimeTravelFacade = new TimeTravelFacadeBuilder(dbg)
                                         .WithPositions(new PositionsResult(new[]
            {
                new PositionsRecord(1, new Position(0, 0), true),
                new PositionsRecord(2, new Position(0, 0), false)
            })).Build();
            var serverClientBuilder = new ServerClientBuilder();

            tagMethod.ServerClient = serverClientBuilder
                                     .WithAddTag(new Position(0, 0), new[] { 1 }, "This is a note")
                                     .WithAddTag(new Position(0, 0), new[] { 1, 2 }, "This is a note")
                                     .Build();
            tagMethod.Settings = new Settings {
                ProjectName = "test"
            };
            var options = new AddTagOptions
            {
                Text = "This is a note",
                IsAllThreadsAtPosition = false
            };

            var options2 = new AddTagOptions
            {
                Text = "This is a note",
                IsAllThreadsAtPosition = true
            };

            tagMethod.AddTag(options);
            tagMethod.AddTag(options2);
            serverClientBuilder.Mock.Verify(client => client.AddTag(new Position(0, 0), new[] { 1 }, "This is a note"),
                                            Times.Once);
            serverClientBuilder.Mock.Verify(
                client => client.AddTag(new Position(0, 0), new[] { 1, 2 }, "This is a note"), Times.Once);
        }
Пример #2
0
        /// <summary>
        /// Prints as PDF asynchronously.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="options">The options.</param>
        /// <param name="variables">The variables.</param>
        /// <param name="createLinksForHeadings">if set to <c>true</c> creates links for headings.</param>
        /// <returns>
        /// A task with the PDF file path as a result.
        /// </returns>
        /// <exception cref="System.IO.FileNotFoundException">File not found: {fullPath}.</exception>
        internal async Task <string> PrintAsPdfAsync(
            string input,
            HtmlToPdfOptions options,
            Dictionary <string, string> variables,
            bool createLinksForHeadings = true)
        {
            string fullPath = Path.GetFullPath(input);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException($"File not found: {fullPath}", fullPath);
            }

            string tempPdfFilePath = TempPdfFile.Create();

            NavigationOptions navigationOptions = new NavigationOptions
            {
                WaitUntil = new[] { WaitUntilNavigation.Networkidle0 },
                Timeout   = 0,
            };

            AddTagOptions addTagOptions = null;

            if (!string.IsNullOrEmpty(options.StyleSheet))
            {
                if (File.Exists(options.StyleSheet))
                {
                    addTagOptions = new AddTagOptions
                    {
                        Type = "text/css",
                        Path = options.StyleSheet,
                    };
                }
                else
                {
                    this.logger.LogWarning($"File not found: {options.StyleSheet}");
                }
            }

            // the paper format takes priority over width and height
            // if a page width or height is set, unset the paper format
            PaperFormat paperFormat = options.PaperFormat;
            string      width       = options.Width;
            string      height      = options.Height;

            if ((!string.IsNullOrEmpty(width)) ||
                (!string.IsNullOrEmpty(height)))
            {
                paperFormat = null;
            }

            using (TempCopyHtmlFile tempHtmlFile = new TempCopyHtmlFile(fullPath))
            {
                this.PrependEmptyPages(tempHtmlFile.FilePath, options.PageOffset + options.PageNumberOffset);

                // TODO: do not create links for headings if not generating an outline
                if (createLinksForHeadings)
                {
                    this.CreateLinksForHeadings(tempHtmlFile.FilePath);
                }

                string pageRanges = string.Empty;
                if ((options.PageOffset + options.PageNumberOffset) > 0)
                {
                    int fromPage = options.PageOffset + options.PageNumberOffset + 1;
                    int toPage   = options.PageOffset + options.PageNumberOffset + options.NumberOfPages;

                    pageRanges = $"{fromPage}-";
                    if (options.NumberOfPages != 0)
                    {
                        pageRanges += $"{toPage}";
                    }

                    this.logger.LogDebug($"Printing pages {pageRanges} of page '{fullPath}'.");
                }

                // page variables
                Dictionary <string, string> pageVariables = new Dictionary <string, string>();
                if (variables != null)
                {
                    foreach (KeyValuePair <string, string> keyValuePair in variables)
                    {
                        pageVariables.Add(keyValuePair.Key, keyValuePair.Value);
                    }
                }

                pageVariables.Add("webpage", fullPath);

                string footerTemplate = string.Empty;
                bool   displayFooter  = options.FooterTemplateBuilder.DisplayTemplate;
                if (displayFooter)
                {
                    footerTemplate = options.FooterTemplateBuilder.Build(pageVariables);
                }

                string headerTemplate = string.Empty;
                bool   displayHeader  = options.HeaderTemplateBuilder.DisplayTemplate;
                if (displayHeader)
                {
                    headerTemplate = options.HeaderTemplateBuilder.Build(pageVariables);
                }

                PdfOptions pdfOptions = new PdfOptions
                {
                    DisplayHeaderFooter = displayHeader || displayFooter,
                    FooterTemplate      = footerTemplate,
                    Format            = paperFormat,
                    HeaderTemplate    = headerTemplate,
                    Height            = height,
                    Landscape         = options.Landscape,
                    MarginOptions     = options.MarginOptions,
                    PreferCSSPageSize = false,
                    PageRanges        = pageRanges,
                    PrintBackground   = options.PrintBackground,
                    Scale             = 1,
                    Width             = width,
                };

                PolicyResult policyResult = await Policy
                                            .Handle <TargetClosedException>()
                                            .Or <Exception>()
                                            .RetryAsync(2, onRetry: (ex, retryCount, context) =>
                {
                    // executed before each retry
                    // ex. PuppeteerSharp.TargetClosedException: Protocol error(IO.read): Target closed. (Page failed to process Inspector.targetCrashed. Exception of type 'PuppeteerSharp.TargetCrashedException' was thrown..    at PuppeteerSharp.Page.OnTargetCrashed()
                    //     at PuppeteerSharp.Page.<Client_MessageReceived>d__230.MoveNext())
                    //     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                    //     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                    //     at PuppeteerSharp.CDPSession.<SendAsync>d__30.MoveNext()
                    //     --- End of stack trace from previous location where exception was thrown ---
                    //     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                    //     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                    //     at PuppeteerSharp.CDPSession.<SendAsync>d__29`1.MoveNext()
                    //     --- End of stack trace from previous location where exception was thrown ---
                    //     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                    //     at PuppeteerSharp.Helpers.ProtocolStreamReader.<ReadProtocolStreamByteAsync>d__1.MoveNext()
                    //     --- End of stack trace from previous location where exception was thrown ---
                    //     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                    //     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                    //     at PuppeteerSharp.Page.<PdfInternalAsync>d__171.MoveNext()
                    //     --- End of stack trace from previous location where exception was thrown ---
                    //     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                    //     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                    //     at PuppeteerSharp.Page.<PdfAsync>d__166.MoveNext()
                    //      --- End of stack trace from previous location where exception was thrown ---
                    //     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                    //     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                    //     at HtmlToPdf.PdfPrinter.<PrintAsPdfAsync>d__3.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf\PdfPrinter.cs:line 167
                    //     --- End of inner exception stack trace ---
                    //     at HtmlToPdf.PdfPrinter.<PrintAsPdfAsync>d__3.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf\PdfPrinter.cs:line 171
                    //     --- End of stack trace from previous location where exception was thrown ---
                    //     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                    //     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                    //     at HtmlToPdf.HtmlToPdfProcessor.<>c__DisplayClass0_1.<<ProcessAsync>b__6>d.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf\HtmlToPdfProcessor.cs:line 183
                    //     --- End of stack trace from previous location where exception was thrown ---
                    //     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                    //     at HtmlToPdf.HtmlToPdfProcessor.<ProcessAsync>d__0.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf\HtmlToPdfProcessor.cs:line 206
                    //     --- End of stack trace from previous location where exception was thrown ---
                    //     Verbose:[PdfCommand.PDF.wkhtmltopdf]got ... HtmlToPdf.Console.exe output 0Bytes
                    //     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                    //     at HtmlToPdf.HtmlToPdfProcessor.<ProcessAsync>d__0.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf\HtmlToPdfProcessor.cs:line 294
                    //     --- End of stack trace from previous location where exception was thrown ---
                    //     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                    //     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                    //     at HtmlToPdf.Console.Program.<RunAsync>d__7.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf.Console\Program.cs:line 216
                    //     Error:[PdfCommand.PDF]Error happen when converting articles/toc.json to Pdf. Details: iTextSharp.text.exceptions.InvalidPdfException: PDF header signature not found.
                    //     at iTextSharp.text.pdf.PdfReader..ctor(ReaderProperties properties, IRandomAccessSource byteSource)
                    //     at Microsoft.DocAsCode.HtmlToPdf.HtmlToPdfConverter.SaveCore(Stream stream)
                    //     at Microsoft.DocAsCode.HtmlToPdf.HtmlToPdfConverter.Save(String outputFileName)
                    //     at Microsoft.DocAsCode.HtmlToPdf.ConvertWrapper.<>c__DisplayClass7_0.<ConvertCore>b__1(ManifestItem tocFile)
                    this.logger.LogWarning(ex.ToString());
                    Thread.Sleep(1000);
                })
                                            .ExecuteAndCaptureAsync(async() =>
                {
                    using (Page page = await this.browser.NewPageAsync())
                    {
                        // disable navigation timeout
                        // otherwise, the following exception occurs:
                        // PuppeteerSharp.NavigationException: Timeout of 30000 ms exceeded ---> System.TimeoutException: Timeout of 30000 ms exceeded
                        page.DefaultNavigationTimeout = 0;
                        page.DefaultTimeout           = 0;

                        await page.GoToAsync(tempHtmlFile.FilePath, navigationOptions);

                        if (addTagOptions != null)
                        {
                            await page.AddStyleTagAsync(addTagOptions);
                        }

                        await page.WaitForTimeoutAsync(options.JavascriptDelayInMilliseconds);

                        try
                        {
                            await page.PdfAsync(tempPdfFilePath, pdfOptions);
                        }
                        finally
                        {
                            await page.CloseAsync();
                        }
                    }
                });

                if (policyResult.Outcome == OutcomeType.Failure)
                {
                    if (policyResult.FinalException is TargetClosedException)
                    {
                        throw policyResult.FinalException;
                    }
                    else
                    {
                        throw new PrintToPdfException(fullPath, policyResult.FinalException);
                    }
                }
            }

            return(tempPdfFilePath);
        }