From a817506125c7eb60d59dd53784ded2b724bd64a2 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 29 Jan 2025 22:09:37 +0100 Subject: [PATCH 1/2] Support `console` family of code highlighters. This adds support for the often used `console` language family and highlights the first line using a new custom highlighter. The rest of the code will be highlighted using json. --- .../Myst/CodeBlocks/EnhancedCodeBlock.cs | 4 ++++ .../EnhancedCodeBlockHtmlRenderer.cs | 15 +++++++++++++- .../CodeBlocks/EnhancedCodeBlockParser.cs | 20 +++++++++++++++++++ .../Myst/Directives/DirectiveHtmlRenderer.cs | 3 ++- .../Slices/Directives/Code.cshtml | 8 +++++++- .../Slices/Directives/_ViewModels.cs | 1 + .../Slices/Layout/_Scripts.cshtml | 2 ++ src/Elastic.Markdown/_static/custom.css | 15 ++++++++++++++ src/Elastic.Markdown/_static/custom.js | 12 +++++++++++ 9 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 src/Elastic.Markdown/_static/custom.js diff --git a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlock.cs b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlock.cs index c4bf88502..b15a4b3cc 100644 --- a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlock.cs +++ b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlock.cs @@ -27,4 +27,8 @@ public class EnhancedCodeBlock(BlockParser parser, ParserContext context) public bool InlineAnnotations { get; set; } public string Language { get; set; } = "unknown"; + + public string? Caption { get; set; } + + public string? ApiCallHeader { get; set; } } diff --git a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockHtmlRenderer.cs b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockHtmlRenderer.cs index 348acb6fe..8dfcc0571 100644 --- a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockHtmlRenderer.cs +++ b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockHtmlRenderer.cs @@ -33,15 +33,27 @@ private static void RenderRazorSlice(RazorSlice slice, HtmlRenderer render private static void RenderCodeBlockLines(HtmlRenderer renderer, EnhancedCodeBlock block) { var commonIndent = GetCommonIndent(block); + var hasCode = false; for (var i = 0; i < block.Lines.Count; i++) { var line = block.Lines.Lines[i]; var slice = line.Slice; + //ensure we never emit an empty line at beginning or start + if ((i == 0 || i == block.Lines.Count - 1) && line.Slice.IsEmptyOrWhitespace()) + continue; var indent = CountIndentation(slice); if (indent >= commonIndent) slice.Start += commonIndent; + + if (!hasCode) + { + renderer.Write($""); + hasCode = true; + } RenderCodeBlockLine(renderer, block, slice, i); } + if (hasCode) + renderer.Write($""); } private static void RenderCodeBlockLine(HtmlRenderer renderer, EnhancedCodeBlock block, StringSlice slice, int lineNumber) @@ -102,7 +114,8 @@ protected override void Write(HtmlRenderer renderer, EnhancedCodeBlock block) { CrossReferenceName = string.Empty,// block.CrossReferenceName, Language = block.Language, - Caption = string.Empty + Caption = block.Caption, + ApiCallHeader = block.ApiCallHeader }); RenderRazorSlice(slice, renderer, block); diff --git a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs index 26b360543..217f519e5 100644 --- a/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs +++ b/src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs @@ -78,6 +78,18 @@ public override bool Close(BlockProcessor processor, Block block) : codeBlock.Info ) ?? "unknown"; + var language = codeBlock.Language; + codeBlock.Language = language switch + { + "console" => "json", + "console-response" => "json", + "console-result" => "json", + "sh" => "bash", + "yml" => "yaml", + "terminal" => "bash", + _ => codeBlock.Language + }; + var lines = codeBlock.Lines; var callOutIndex = 0; @@ -86,6 +98,14 @@ public override bool Close(BlockProcessor processor, Block block) { originatingLine++; var line = lines.Lines[index]; + if (index == 0 && language == "console") + { + codeBlock.ApiCallHeader = line.ToString(); + var s = new StringSlice(""); + lines.Lines[index] = new StringLine(ref s); + continue; + } + var span = line.Slice.AsSpan(); if (span.ReplaceSubstitutions(context.FrontMatter?.Properties, out var replacement)) diff --git a/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs b/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs index fc6a89691..b5f907722 100644 --- a/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs +++ b/src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs @@ -213,7 +213,8 @@ private void WriteLiteralIncludeBlock(HtmlRenderer renderer, IncludeBlock block) { CrossReferenceName = null, Language = block.Language, - Caption = null + Caption = null, + ApiCallHeader = null }); RenderRazorSlice(slice, renderer, content); } diff --git a/src/Elastic.Markdown/Slices/Directives/Code.cshtml b/src/Elastic.Markdown/Slices/Directives/Code.cshtml index 91dacf04d..c75a2597d 100644 --- a/src/Elastic.Markdown/Slices/Directives/Code.cshtml +++ b/src/Elastic.Markdown/Slices/Directives/Code.cshtml @@ -8,6 +8,12 @@ ΒΆ } -
[CONTENT]
+
+		@if (!string.IsNullOrEmpty(Model.ApiCallHeader))
+		{
+			@Model.ApiCallHeader
+		}
+			[CONTENT]
+		
\ No newline at end of file diff --git a/src/Elastic.Markdown/Slices/Directives/_ViewModels.cs b/src/Elastic.Markdown/Slices/Directives/_ViewModels.cs index 853596226..6960dccf9 100644 --- a/src/Elastic.Markdown/Slices/Directives/_ViewModels.cs +++ b/src/Elastic.Markdown/Slices/Directives/_ViewModels.cs @@ -17,6 +17,7 @@ public class AdmonitionViewModel public class CodeViewModel { + public required string? ApiCallHeader { get; init; } public required string? Caption { get; init; } public required string Language { get; init; } public required string? CrossReferenceName { get; init; } diff --git a/src/Elastic.Markdown/Slices/Layout/_Scripts.cshtml b/src/Elastic.Markdown/Slices/Layout/_Scripts.cshtml index 9cfec421e..9658ecc7c 100644 --- a/src/Elastic.Markdown/Slices/Layout/_Scripts.cshtml +++ b/src/Elastic.Markdown/Slices/Layout/_Scripts.cshtml @@ -16,5 +16,7 @@ + + diff --git a/src/Elastic.Markdown/_static/custom.css b/src/Elastic.Markdown/_static/custom.css index 0b759dccb..393d461f8 100644 --- a/src/Elastic.Markdown/_static/custom.css +++ b/src/Elastic.Markdown/_static/custom.css @@ -205,4 +205,19 @@ See https://github.com/elastic/docs-builder/issues/219 for further details .globaltoc a.reference.internal { display: inline-block; width: 100% +} + + +.code-block-caption .caption-text { + color: var(--yue-c-code-text); + font-family: ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace; + line-height: 1.48; + font-size: .96rem; + font-weight: 400; +} + +code.language-apiheader:has(+ code) { + padding-bottom: 0.4em; + margin-bottom: 0.4em; + border-bottom: 1px solid #dfdfdf; } \ No newline at end of file diff --git a/src/Elastic.Markdown/_static/custom.js b/src/Elastic.Markdown/_static/custom.js new file mode 100644 index 000000000..17388341c --- /dev/null +++ b/src/Elastic.Markdown/_static/custom.js @@ -0,0 +1,12 @@ +hljs.registerLanguage('apiheader', function() { + return { + case_insensitive: true, // language is case-insensitive + keywords: 'GET POST PUT DELETE HEAD OPTIONS PATCH', + contains: [ + hljs.HASH_COMMENT_MODE, + { + className: "subst", // (pathname: path1/path2/dothis) color #ab5656 + begin: /(?<=(?:\/|GET |POST |PUT |DELETE |HEAD |OPTIONS |PATH))[^?\n\r\/]+/, + } + ], } +}) From 1dce903cc3b3745a7e7539f7e207cb09e16556d8 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Thu, 30 Jan 2025 12:14:14 +0100 Subject: [PATCH 2/2] add console syntax documentation --- docs/syntax/code.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/docs/syntax/code.md b/docs/syntax/code.md index c33fe7180..12cae9623 100644 --- a/docs/syntax/code.md +++ b/docs/syntax/code.md @@ -91,3 +91,38 @@ will output: var apiKey = new ApiKey(""); // However this is var client = new ElasticsearchClient("", apiKey); ``` + + +## Console output + +We document alot of API endpoints at Elastic for this you can use `console` as language. The term console relates to the dev console in kibana which users can link to directly from these code snippets. + +:::{note} +We are still actively developing this special block and it's features +::: + +````markdown +```console +GET /mydocuments/_search +{ + "from": 1, + "query": { + "match_all" {} + } +} +``` +```` + +Will render as: + +```console +GET /mydocuments/_search +{ + "from": 1, + "query": { + "match_all" {} + } +} +``` + +The first line is highlighted as a dev console string and the remainder as json.