private static IEnumerable <string> GetInteractiveHtmlImpl(IEnumerable <object> vs) { yield return("<!doctype html>\n<html><head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>Console Log Inspector (Show-ConsoleLog)</title>\n<link href=\"file:///"); yield return(HtmlEncode(InteractiveStylesPath.Replace("\\", "/"))); yield return("\" rel=\"stylesheet\" />\n</head><body>\n"); int ctr = 0; string[] spaces = null; bool emptyConsole = true; bool emptyLine = true; foreach (object obj in vs) { ConsoleLog consoleLog = obj as ConsoleLog; if (!ReferenceEquals(consoleLog, null)) { yield return("<div class=\"container console\" role=\"main\" aria-label=\"Console Log Inspector\"><input type=\"checkbox\" id=\"ctrl"); yield return(ctr.ToString(CultureInfo.InvariantCulture)); yield return("\" checked=\"checked\" /><label for=\"ctrl"); yield return(ctr.ToString(CultureInfo.InvariantCulture)); yield return("\" role=\"heading\" aria-level=\"1\" aria-label=\"ConsoleLog object, width "); string width = consoleLog.Width.ToString(CultureInfo.InvariantCulture); spaces = new string[width.Length]; for (int i = 0; i != width.Length; ++i) { spaces[i] = new string(' ', i); } yield return(width); yield return(", see checkbox before this heading for expansion collapsion state, press Space to toggle\"><span class=\"color fg-"); yield return(ColorToName(consoleLog.Foreground)); yield return(" bg-"); yield return(ColorToName(consoleLog.Background)); yield return("\">ConsoleLog</span> object (width = "); yield return(width); yield return(")</label><div class=\"content\">\n"); ++ctr; continue; } Line line = obj as Line; if (!ReferenceEquals(line, null)) { yield return("<div class=\"container line\"><input type=\"checkbox\" id=\"ctrl"); yield return(ctr.ToString(CultureInfo.InvariantCulture)); yield return("\" checked=\"checked\" /><label for=\"ctrl"); yield return(ctr.ToString(CultureInfo.InvariantCulture)); yield return("\" role=\"heading\" aria-level=\"2\" aria-label=\"Line object, see checkbox before this heading for expansion collapsion state, press Space to toggle\"><span class=\"color fg-"); yield return(ColorToName(line.Foreground)); yield return(" bg-"); yield return(ColorToName(line.Background)); yield return("\">Line</span> object</label><div class=\"content\">\n"); emptyConsole = false; emptyLine = true; ++ctr; continue; } Span span = obj as Span; if (!ReferenceEquals(span, null)) { yield return("<div class=\"span\">Span (width = "); string width = span.Width.ToString(CultureInfo.InvariantCulture); if (width.Length < spaces.Length) { yield return(spaces[spaces.Length - width.Length]); } yield return(width); yield return("): <span class=\"color fg-"); yield return(ColorToName(span.Foreground)); yield return(" bg-"); yield return(ColorToName(span.Background)); yield return("\" role=\"img\" aria-label=\"foreground color "); yield return(ColorToFriendlyName(span.Foreground)); yield return(", background color "); yield return(ColorToFriendlyName(span.Background)); yield return(", content: "); string htmlContent = HtmlEncode(span.Content); yield return(htmlContent); yield return("\">"); yield return(htmlContent); yield return("</span></div>\n"); emptyLine = false; continue; } yield return(emptyLine ? "<div class=\"none\">(no Span subobject)</div></div></div>\n" : "</div></div>\n"); } yield return(emptyConsole ? "<div class=\"none\">(no Line subobject)</div></div>\n</body></html>\n" : "</div></div>\n</body></html>\n"); }
/// <summary> /// Enumerates the substrings of HTML-formatted ConsoleLog. /// </summary> /// <param name="host">$Host from PowerShell.</param> /// <param name="includeCurrentLine">Whether the current line should be included. /// This can be set to $False if the command is used interactively.</param> /// <param name="behavior">Behavior of trailing space characters.</param> public static IEnumerable <string> StreamCapture(PSHost host, bool includeCurrentLine, TrailingSpaceBehavior behavior) { ConsoleColor fgDefault = ConsoleColor.White, bgDefault = ConsoleColor.Black; ConsoleColor fgLine = ConsoleColor.White, bgLine = ConsoleColor.Black; ConsoleColor fg = ConsoleColor.White, bg = ConsoleColor.Black; bool emptyLine = true; /* The loop directly walks the tree, so we do not need ** the tree to be stored in the returned objects. ** Setting "populate" to $False make it GC-efficient. */ foreach (object obj in Capturer.StreamCapture(host, includeCurrentLine, behavior, false)) { ConsoleLog console = obj as ConsoleLog; if (!ReferenceEquals(console, null)) { yield return("<pre class=\"gl-console gl-console-fg-"); yield return(Helper.ColorToName(fgDefault = console.Foreground)); yield return(" gl-console-bg-"); yield return(Helper.ColorToName(bgLine = bgDefault = console.Background)); yield return("\" data-width=\""); yield return(console.Width.ToString(CultureInfo.InvariantCulture)); yield return("\">\n"); continue; } Line line = obj as Line; if (!ReferenceEquals(line, null)) { yield return("<code class=\"gl-console-line"); if ((fgLine = line.Foreground) != fgDefault) { yield return(" gl-console-fg-"); yield return(Helper.ColorToName(fgLine)); } yield return(" gl-console-bg-"); ConsoleColor bgLine2 = line.Background; if (bgLine != bgLine2) { yield return("change gl-console-bg-"); } yield return((bgLine = bgLine2) != bgDefault ? Helper.ColorToName(bgLine2) : "none"); yield return("\">"); emptyLine = true; continue; } Span span = obj as Span; if (!ReferenceEquals(span, null)) { emptyLine = false; fg = span.Foreground; bg = span.Background; if (fg == fgLine && bg == bgLine) { yield return("<span>"); yield return(Helper.HtmlEncode(span.Content)); yield return("</span>"); } else if (fg == fgLine && bg != bgLine) { yield return("<span class=\"gl-console-bg-"); yield return(Helper.ColorToName(bg)); yield return("\">"); yield return(Helper.HtmlEncode(span.Content)); yield return("</span>"); } else if (fg != fgLine && bg == bgLine) { yield return("<span class=\"gl-console-fg-"); yield return(Helper.ColorToName(fg)); yield return("\">"); yield return(Helper.HtmlEncode(span.Content)); yield return("</span>"); } else { yield return("<span class=\"gl-console-fg-"); yield return(Helper.ColorToName(fg)); yield return(" gl-console-bg-"); yield return(Helper.ColorToName(bg)); yield return("\">"); yield return(Helper.HtmlEncode(span.Content)); yield return("</span>"); } continue; } /* A line has ended. */ yield return(emptyLine ? "<span> </span></code>\n" : "</code>\n"); } yield return("</pre>"); }