internal static void HighlightElement(IJavaScriptEnginePool enginePool, AngleSharp.Dom.IElement element) { using (IJavaScriptEngine engine = enginePool.GetEngine()) { // Make sure to use TextContent, otherwise you'll get escaped html which highlight.js won't parse engine.SetVariableValue("input", element.TextContent); // Check if they specified a language in their code block string language = element.ClassList.FirstOrDefault(i => i.StartsWith("language")); if (language != null) { engine.SetVariableValue("language", language.Replace("language-", string.Empty)); engine.Execute("result = hljs.highlight(language, input)"); } else { language = "(auto)"; // set this to auto in case there is an exception below engine.Execute("result = hljs.highlightAuto(input)"); string detectedLanguage = engine.Evaluate <string>("result.language"); if (!string.IsNullOrWhiteSpace(detectedLanguage)) { element.ClassList.Add("language-" + detectedLanguage); } } element.ClassList.Add("hljs"); element.InnerHtml = engine.Evaluate <string>("result.value"); } }
/// <inheritdoc /> public override async Task <IDocument> ExecuteAsync(KeyValuePair <string, string>[] args, string content, IDocument document, IExecutionContext context) { IMetadataDictionary dictionary = args.ToDictionary( "Language", "Element", "HighlightJsFile"); HtmlParser parser = new HtmlParser(); using (IJavaScriptEnginePool enginePool = context.GetJavaScriptEnginePool(x => { if (dictionary.ContainsKey("HighlightJsFile")) { x.ExecuteFile(dictionary.GetString("HighlightJsFile")); } else { x.ExecuteResource("highlight-all.js", typeof(Statiq.Highlight.HighlightCode)); } })) { AngleSharp.Dom.IDocument htmlDocument = parser.Parse(string.Empty); AngleSharp.Dom.IElement element = htmlDocument.CreateElement(dictionary.GetString("Element", "code")); element.InnerHtml = content.Trim(); if (dictionary.ContainsKey("Language")) { element.SetAttribute("class", $"language-{dictionary.GetString("Language")}"); } Statiq.Highlight.HighlightCode.HighlightElement(enginePool, element); return(context.CreateDocument(await context.GetContentProviderAsync(element.OuterHtml))); } }
/// <inheritdoc /> public IShortcodeResult Execute(KeyValuePair <string, string>[] args, string content, IDocument document, IExecutionContext context) { ConvertingDictionary dictionary = args.ToDictionary( context, "Language", "Element", "HighlightJsFile"); HtmlParser parser = new HtmlParser(); using (IJavaScriptEnginePool enginePool = context.GetJavaScriptEnginePool(x => { if (dictionary.ContainsKey("HighlightJsFile")) { x.ExecuteFile(dictionary.String("HighlightJsFile")); } else { x.ExecuteResource("highlight-all.js", typeof(Wyam.Highlight.Highlight)); } })) { AngleSharp.Dom.IDocument htmlDocument = parser.Parse(string.Empty); AngleSharp.Dom.IElement element = htmlDocument.CreateElement(dictionary.String("Element", "code")); element.InnerHtml = content.Trim(); if (dictionary.ContainsKey("Language")) { element.SetAttribute("class", $"language-{dictionary.String("Language")}"); } Wyam.Highlight.Highlight.HighlightElement(enginePool, element); return(context.GetShortcodeResult(element.OuterHtml)); } }
/// <inheritdoc /> protected override async Task <IEnumerable <IDocument> > ExecuteContextAsync(IExecutionContext context) { HtmlParser parser = new HtmlParser(); IJavaScriptEnginePool enginePool = context.GetJavaScriptEnginePool(x => { if (string.IsNullOrWhiteSpace(_highlightJsFile)) { x.ExecuteResource("highlight-all.js", typeof(HighlightCode)); } else { x.ExecuteFile(_highlightJsFile); } }); using (enginePool) { IEnumerable <IDocument> results = await context.Inputs.ParallelSelectAsync(async input => { try { using (Stream stream = input.GetContentStream()) { using (IHtmlDocument htmlDocument = await parser.ParseAsync(stream)) { foreach (AngleSharp.Dom.IElement element in htmlDocument.QuerySelectorAll(_codeQuerySelector)) { // Don't highlight anything that potentially is already highlighted if (element.ClassList.Contains("hljs")) { continue; } try { HighlightElement(enginePool, element); } catch (Exception innerEx) { if (innerEx.Message.Contains("Unknown language: ") && _warnOnMissingLanguage) { context.LogWarning($"Exception while highlighting source code: {innerEx.Message}"); } else { context.LogInformation($"Exception while highlighting source code: {innerEx.Message}"); } } } using (Stream contentStream = await context.GetContentStreamAsync()) { using (StreamWriter writer = contentStream.GetWriter()) { htmlDocument.ToHtml(writer, HtmlMarkupFormatter.Instance); writer.Flush(); return(input.Clone(context.GetContentProvider(contentStream, MediaTypes.Html))); } } } } } catch (Exception ex) { context.LogWarning("Exception while highlighting source code for {0}: {1}", input.ToSafeDisplayString(), ex.Message); return(input); } }); // Materialize the results before disposing the JS engine return(results.ToList()); } }
/// <inheritdoc /> public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context) { HtmlParser parser = new HtmlParser(); using (IJavaScriptEnginePool enginePool = context.GetJavaScriptEnginePool(x => { if (string.IsNullOrWhiteSpace(_highlightJsFile)) { x.ExecuteResource("highlight-all.js", typeof(Highlight)); } else { x.ExecuteFile(_highlightJsFile); } })) { return(inputs.AsParallel().Select(context, input => { try { using (Stream stream = input.GetStream()) { using (IHtmlDocument htmlDocument = parser.Parse(stream)) { foreach (AngleSharp.Dom.IElement element in htmlDocument.QuerySelectorAll(_codeQuerySelector)) { // Don't highlight anything that potentially is already highlighted if (element.ClassList.Contains("hljs")) { continue; } try { HighlightElement(enginePool, element); } catch (Exception innerEx) { if (innerEx.Message.Contains("Unknown language: ") && _warnOnMissingLanguage) { Trace.Warning($"Exception while highlighting source code: {innerEx.Message}"); } else { Trace.Information($"Exception while highlighting source code: {innerEx.Message}"); } } } Stream contentStream = context.GetContentStream(); using (StreamWriter writer = contentStream.GetWriter()) { htmlDocument.ToHtml(writer, HtmlMarkupFormatter.Instance); writer.Flush(); return context.GetDocument(input, contentStream); } } } } catch (Exception ex) { Trace.Warning("Exception while highlighting source code for {0}: {1}", input.SourceString(), ex.Message); return input; } }).ToList()); } }