FlexiCodeBlocks
November 15, 2019 ยท View on GitHub
A FlexiCodeBlock displays code. FlexiCodeBlocks enhance code aesthetically and functionally with features like syntax highlighting, line highlighting, phrase highlighting, line numbering and more.
Prerequisites
To use syntax highlighting, NodeJS must be installed and node.exe's directory must be added to the Path environment variable.
Usage
using Markdig;
using Jering.Markdig.Extensions.FlexiBlocks;
...
var markdownPipelineBuilder = new MarkdownPipelineBuilder();
markdownPipelineBuilder.UseFlexiCodeBlocks(/* Optional extension options */);
MarkdownPipeline markdownPipeline = markdownPipelineBuilder.Build();
string markdown = @"```
public string ExampleFunction(string arg)
{
// Example comment
return arg + ""dummyString"";
}
```"
string html = Markdown.ToHtml(markdown, markdownPipeline);
string expectedHtml = @"<div class=""flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"">
<header class=""flexi-code__header"">
<span class=""flexi-code__title""></span>
<button class=""flexi-code__copy-button"" aria-label=""Copy code"">
<svg class=""flexi-code__copy-icon"" xmlns=""http://www.w3.org/2000/svg"" width=""18px"" height=""18px"" viewBox=""0 0 18 18""><path fill=""none"" d=""M0,0h18v18H0V0z""/><path d=""M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z""/></svg>
</button>
</header>
<pre class=""flexi-code__pre""><code class=""flexi-code__code"">public string ExampleFunction(string arg)
{
// Example comment
return arg + "dummyString";
}
</code></pre>
</div>";
Assert.Equal(expectedHtml, html)
Basics
In markdown, a FlexiCodeBlock is a sequence of fenced or indented lines - identical to CommonMark code blocks. For example:
--------------- Markdown ---------------
```
public string ExampleFunction(string arg)
{
// Example comment
return arg + "dummyString";
}
```
--------------- Expected Markup ---------------
<div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases">
<header class="flexi-code__header">
<button class="flexi-code__copy-button" aria-label="Copy code">
<svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg>
</button>
</header>
<pre class="flexi-code__pre"><code class="flexi-code__code">public string ExampleFunction(string arg)
{
// Example comment
return arg + "dummyString";
}
</code></pre>
</div>
! By default, a FlexiCodeBlock has a header, a copy button and more. Each element is assigned a default class. Default classes comply with
! BEM methodology.
!
! FlexiCodeBlocks can be customized, we explain how in [options].
Like CommonMark code blocks, a FlexiCodeBlock's fence can consist of tildes:
--------------- Markdown ---------------
~~~
<html>
<head>
<title>Example Page</title>
</head>
<body>
<p>Example content.</p>
</body>
</html>
~~~
--------------- Expected Markup ---------------
<div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases">
<header class="flexi-code__header">
<button class="flexi-code__copy-button" aria-label="Copy code">
<svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg>
</button>
</header>
<pre class="flexi-code__pre"><code class="flexi-code__code"><html>
<head>
<title>Example Page</title>
</head>
<body>
<p>Example content.</p>
</body>
</html>
</code></pre>
</div>
The following is an indented FlexiCodeBlock:
--------------- Markdown ---------------
public exampleFunction(arg: string): string {
// Example comment
return arg + "dummyString";
}
--------------- Expected Markup ---------------
<div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases">
<header class="flexi-code__header">
<button class="flexi-code__copy-button" aria-label="Copy code">
<svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg>
</button>
</header>
<pre class="flexi-code__pre"><code class="flexi-code__code">public exampleFunction(arg: string): string {
// Example comment
return arg + "dummyString";
}
</code></pre>
</div>
Options
FlexiCodeBlockOptions
Options for a FlexiCodeBlock. To specify FlexiCodeBlockOptions for a FlexiCodeBlock, the Options extension must be enabled.
Properties
BlockName
- Type:
string - Description: The
FlexiCodeBlock's BEM block name. In compliance with BEM methodology, this value is theFlexiCodeBlock's root element's class as well as the prefix for all other classes in the block. This value should contain only valid CSS class characters. If this value isnull, whitespace or an empty string, theFlexiCodeBlock's block name is "flexi-code". - Default: "flexi-code"
- Examples:
--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "blockName": "code" } ``` public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } ``` --------------- Expected Markup --------------- <div class="code code_no-title code_has-copy-icon code_has-header code_no-syntax-highlights code_no-line-numbers code_has-omitted-lines-icon code_no-highlighted-lines code_no-highlighted-phrases"> <header class="code__header"> <button class="code__copy-button" aria-label="Copy code"> <svg class="code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="code__pre"><code class="code__code">public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } </code></pre> </div>
Title
- Type:
string - Description: The
FlexiCodeBlock's title. If this value isnull, whitespace or an empty string, no title is rendered. - Default:
null - Examples:
--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "title" : "ExampleDocument.cs" } ``` public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_has-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <span class="flexi-code__title">ExampleDocument.cs</span> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code">public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } </code></pre> </div>
CopyIcon
- Type:
string - Description: The
FlexiCodeBlock's copy button icon as an HTML fragment. The class "<BlockName>__copy-icon" is assigned to this fragment's first start tag. If this value isnull, whitespace or an empty string, no copy icon is rendered. - Default: a copy file icon
- Examples:
No copy icon is are rendered if this value is--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "copyIcon": "<svg><use xlink:href=\"#material-design-copy\"/></svg>" } ``` public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon"><use xlink:href="#material-design-copy"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code">public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } </code></pre> </div>null, whitespace or an empty string:--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "copyIcon": null } ``` public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_no-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code">public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } </code></pre> </div>
RenderHeader
- Type:
bool - Description: The value specifying whether to render the
FlexiCodeBlock's header. Iffalse, the header element, which contains theFlexiCodeBlock's title and copy button, is not rendered. - Default:
true - Examples:
--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "renderHeader": "false" } ``` public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_no-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <pre class="flexi-code__pre"><code class="flexi-code__code">public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } </code></pre> </div>
Language
- Type:
string - Description: The programming language of the
FlexiCodeBlock's code. IfSyntaxHighlighteris notSyntaxHighlighter.None, this value is passed to the chosen syntax highlighter. Therefore, this value must be a language alias supported by the chosen syntax highlighter. Valid language aliases for Prism. Valid language aliases for HighlightJS. The class "<BlockName>_code_language" is assigned to the FlexiCodeBlock's root element. If this value isnull, whitespace or an empty string, syntax highlighting is disabled and no language class is assigned to the root element. - Default:
null - Examples:
--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "language": "csharp" } ``` public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_language_csharp flexi-code_has-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code"><span class="token keyword">public</span> <span class="token keyword">string</span> <span class="token function">ExampleFunction</span><span class="token punctuation">(</span><span class="token keyword">string</span> arg<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Example comment</span> <span class="token keyword">return</span> arg <span class="token operator">+</span> <span class="token string">"dummyString"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> </div>
SyntaxHighlighter
- Type:
SyntaxHighlighter - Description: The syntax highlighter to highlight the
FlexiCodeBlock's code with. If this value isSyntaxHighlighter.None, orLanguageisnull, whitespace or an empty string, syntax highlighting is disabled. Syntax highlighting requires Node.js to be installed and on the path environment variable. - Default:
SyntaxHighlighter.Prism - Examples:
--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "syntaxHighlighter": "highlightJS", "language": "typescript" } ``` public exampleFunction(arg: string): string { // Example comment return arg + "dummyString"; } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_language_typescript flexi-code_has-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code"><span class="hljs-keyword">public</span> exampleFunction(arg: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">string</span> { <span class="hljs-comment">// Example comment</span> <span class="hljs-keyword">return</span> arg + <span class="hljs-string">"dummyString"</span>; } </code></pre> </div>
LineNumbers
- Type:
IList<NumberedLineRange> - Description: The
NumberedLineRanges specifying line numbers to render. If line numbers are specified for some but not all lines, an omitted lines icon is rendered for each line with no line number. You can customize the icon by specifyingOmittedLinesIcon. If line numbers are specified for some but not all lines, an omitted lines notice is inserted into each empty line with no line number. The notice "line {0} omitted for brevity" is inserted if a single line is omitted and the notice "lines {0} to {1} omitted for brevity", is inserted if multiple lines are omitted. Contained ranges must not overlap. If this value isnull, no line numbers are rendered. - Default:
null - Examples:
--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "lineNumbers": [ { "startLine": 2, "endLine": 8, "startNumber": 4 }, { "startLine": 10, "endLine": -2, "startNumber": 32 } ] } ``` public class ExampleClass { public string ExampleFunction1(string arg) { // Example comment return arg + "dummyString"; } public string ExampleFunction3(string arg) { // Example comment return arg + "dummyString"; } } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_has-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code"><span class="flexi-code__line-prefix"><svg class="flexi-code__omitted-lines-icon" xmlns="http://www.w3.org/2000/svg" width="2px" height="10px" viewBox="0 0 2 10"><rect shape-rendering="crispEdges" width="2" height="2"/><rect shape-rendering="crispEdges" y="4" width="2" height="2"/><rect shape-rendering="crispEdges" y="8" width="2" height="2"/></svg></span><span class="flexi-code__line flexi-code__line_omitted-lines">Lines 1 to 3 omitted for brevity</span> <span class="flexi-code__line-prefix">4</span><span class="flexi-code__line">public class ExampleClass</span> <span class="flexi-code__line-prefix">5</span><span class="flexi-code__line">{</span> <span class="flexi-code__line-prefix">6</span><span class="flexi-code__line"> public string ExampleFunction1(string arg)</span> <span class="flexi-code__line-prefix">7</span><span class="flexi-code__line"> {</span> <span class="flexi-code__line-prefix">8</span><span class="flexi-code__line"> // Example comment</span> <span class="flexi-code__line-prefix">9</span><span class="flexi-code__line"> return arg + "dummyString";</span> <span class="flexi-code__line-prefix">10</span><span class="flexi-code__line"> }</span> <span class="flexi-code__line-prefix"><svg class="flexi-code__omitted-lines-icon" xmlns="http://www.w3.org/2000/svg" width="2px" height="10px" viewBox="0 0 2 10"><rect shape-rendering="crispEdges" width="2" height="2"/><rect shape-rendering="crispEdges" y="4" width="2" height="2"/><rect shape-rendering="crispEdges" y="8" width="2" height="2"/></svg></span><span class="flexi-code__line flexi-code__line_omitted-lines">Lines 11 to 31 omitted for brevity</span> <span class="flexi-code__line-prefix">32</span><span class="flexi-code__line"> public string ExampleFunction3(string arg)</span> <span class="flexi-code__line-prefix">33</span><span class="flexi-code__line"> {</span> <span class="flexi-code__line-prefix">34</span><span class="flexi-code__line"> // Example comment</span> <span class="flexi-code__line-prefix">35</span><span class="flexi-code__line"> return arg + "dummyString";</span> <span class="flexi-code__line-prefix">36</span><span class="flexi-code__line"> }</span> <span class="flexi-code__line-prefix">37</span><span class="flexi-code__line">}</span> <span class="flexi-code__line-prefix"><svg class="flexi-code__omitted-lines-icon" xmlns="http://www.w3.org/2000/svg" width="2px" height="10px" viewBox="0 0 2 10"><rect shape-rendering="crispEdges" width="2" height="2"/><rect shape-rendering="crispEdges" y="4" width="2" height="2"/><rect shape-rendering="crispEdges" y="8" width="2" height="2"/></svg></span><span class="flexi-code__line flexi-code__line_omitted-lines">Lines 38 to the end omitted for brevity</span> </code></pre> </div>
OmittedLinesIcon
- Type:
string - Description: The
FlexiCodeBlock's omitted lines icon as an HTML fragment. The class "<BlockName>__omitted-lines-icon" is assigned to this fragment's first start tag. If this value isnull, whitespace or an empty string, no omitted lines icons are rendered. - Default: a vertical ellipsis icon
- Examples:
No omitted lines icons are rendered if this value is--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "omittedLinesIcon": "<svg><use xlink:href=\"#material-design-more-vert\"/></svg>", "lineNumbers": [{"endLine": 2}, {"startLine": 4, "startNumber":10}] } ``` public string ExampleFunction(string arg) { } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_has-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code"><span class="flexi-code__line-prefix">1</span><span class="flexi-code__line">public string ExampleFunction(string arg)</span> <span class="flexi-code__line-prefix">2</span><span class="flexi-code__line">{</span> <span class="flexi-code__line-prefix"><svg class="flexi-code__omitted-lines-icon"><use xlink:href="#material-design-more-vert"/></svg></span><span class="flexi-code__line flexi-code__line_omitted-lines">Lines 3 to 9 omitted for brevity</span> <span class="flexi-code__line-prefix">10</span><span class="flexi-code__line">}</span> </code></pre> </div>null, white space or an empty string:--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "omittedLinesIcon": null, "lineNumbers": [{"endLine": 2}, {"startLine": 4, "startNumber":10}] } ``` public string ExampleFunction(string arg) { } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_has-line-numbers flexi-code_no-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code"><span class="flexi-code__line-prefix">1</span><span class="flexi-code__line">public string ExampleFunction(string arg)</span> <span class="flexi-code__line-prefix">2</span><span class="flexi-code__line">{</span> <span class="flexi-code__line-prefix"></span><span class="flexi-code__line flexi-code__line_omitted-lines">Lines 3 to 9 omitted for brevity</span> <span class="flexi-code__line-prefix">10</span><span class="flexi-code__line">}</span> </code></pre> </div>
HighlightedLines
- Type:
IList<LineRange> - Description: The
LineRanges specifying lines to highlight. If this value isnull, no lines are highlighted. - Default:
null - Examples:
--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "highlightedLines": [ { "endLine": 1 }, { "startLine": 3, "endLine": 4 } ] } ``` public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_has-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code"><span class="flexi-code__line flexi-code__line_highlighted">public string ExampleFunction(string arg)</span> { <span class="flexi-code__line flexi-code__line_highlighted"> // Example comment</span> <span class="flexi-code__line flexi-code__line_highlighted"> return arg + "dummyString";</span> } </code></pre> </div>
HighlightedPhrases
- Type:
IList<PhraseGroup> - Description: The
PhraseGroups specifying phrases to highlight. If the regex expression of aPhraseGrouphas groups, only groups are highlighted, entire matches are not highlighted. If the regex expression of aPhraseGrouphas no groups, entire matches are highlighted. If this value isnull, no phrases are highlighted. - Default:
null - Examples:
--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "highlightedPhrases": [ { "regex": "return (.*?);", "includedMatches": [1] }, { "regex": "string arg" } ] } ``` public class ExampleClass { public string ExampleFunction1(string arg) { // Example comment return arg + "dummyString"; } public string ExampleFunction2(string arg) { // Example comment return arg + "dummyString"; } } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_has-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code">public class ExampleClass { public string ExampleFunction1(<span class="flexi-code__highlighted-phrase">string arg</span>) { // Example comment return arg + "dummyString"; } public string ExampleFunction2(<span class="flexi-code__highlighted-phrase">string arg</span>) { // Example comment return <span class="flexi-code__highlighted-phrase">arg + "dummyString"</span>; } } </code></pre> </div>
RenderingMode
- Type:
FlexiCodeBlockRenderingMode - Description: The
FlexiCodeBlock's rendering mode. - Default:
FlexiCodeBlockRenderingMode.Standard - Examples:
This value is
FlexiCodeBlockRenderingMode.Standardby default:
If this value is--------------- Markdown --------------- ``` public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code">public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } </code></pre> </div>FlexiCodeBlockRenderingMode.Classic, theFlexiCodeBlockis rendered the same way code blocks are rendered in CommonMark Spec examples:--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "renderingMode": "classic" } ``` public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } ``` --------------- Expected Markup --------------- <pre><code>public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } </code></pre>
Attributes
- Type:
IDictionary<string, string> - Description: The HTML attributes for the
FlexiCodeBlock's root element. Attribute names must be lowercase. If classes are specified, they are appended to default classes. This facilitates BEM mixes. If this value isnull, default classes are still assigned to the root element. - Default:
null - Examples:
--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Markdown --------------- o{ "attributes": { "id" : "code-1", "class" : "block" } } ``` public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases block" id="code-1"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code">public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } </code></pre> </div>
LineRange
Represents a range of lines.
Properties
StartLine
- Type:
int - Description: The line number of the
LineRange's start line. If this value is-n, the start line is the nth last line. For example, if this value is-2, the start line is the 2nd last line. This value must not be0. - Default:
1
EndLine
- Type:
int - Description: The line number of the
LineRange's end line. If this value is-n, the end line is the nth last line. For example, if this value is-2, the end line is the 2nd last line. This value must not be0or an integer representing a line before the start line. - Default:
-1
NumberedLineRange
Represents a range of lines with an associated sequence of numbers.
Properties
StartLine
- Type:
int - Description: The line number of the
NumberedLineRange's start line. If this value is-n, the start line is the nth last line. For example, if this value is-2, the start line is the 2nd last line. This value must not be0. - Default:
1
EndLine
- Type:
int - Description: The line number of the
NumberedLineRange's end line. If this value is-n, the end line is the nth last line. For example, if this value is-2, the end line is the 2nd last line. This value must not be0or an integer representing a line before the start line. - Default:
-1
StartNumber
- Type:
int - Description: The number associated with this
NumberedLineRange's start line. The number associated with each subsequent line is incremented by 1. This value must be greater than 0. - Default:
1
PhraseGroup
Represents phrases in a body of text.
Properties
Regex
- Type:
string - Description: The regex expression for the
PhraseGroup. This value is required.
IncludedMatches
- Type:
int[] - Description: The indices of the regex matches included in the
PhraseGroup. This array can contain negative values. If a value is-n, the nth last match is included. For example, if a value is-2, the 2nd last match is included. If this value isnullor empty, all matches are included. - Default:
null
FlexiCodeBlocksExtensionOptions
Options for the FlexiCodeBlocks extension. There are two ways to specify these options:
- Pass a
FlexiCodeBlocksExtensionOptionswhen callingMarkdownPipelineBuilderExtensions.UseFlexiCodeBlocks(this MarkdownPipelineBuilder pipelineBuilder, IFlexiCodeBlocksExtensionOptions options). - Insert a
FlexiCodeBlocksExtensionOptionsinto aMarkdownParserContext.Propertieswith keytypeof(IFlexiCodeBlocksExtensionOptions). Pass theMarkdownParserContextwhen you call a markdown processing method likeMarkdown.ToHtml(markdown, stringWriter, markdownPipeline, yourMarkdownParserContext).
This method allows for different extension options when reusing a pipeline. Options specified using this method take precedence.
Constructor Parameters
defaultBlockOptions
-
Type:
IFlexiCodeBlockOptions -
Description: Default
IFlexiCodeBlockOptionsfor allFlexiCodeBlocks. If this value isnull, aFlexiCodeBlockOptionswith default values is used. -
Default:
null -
Examples:
--------------- Extension Options --------------- { "flexiCodeBlocks": { "defaultBlockOptions": { "blockName": "code", "title": "ExampleDocument.cs", "copyIcon": "<svg><use xlink:href=\"#material-design-copy\"/></svg>", "language": "html", "syntaxHighlighter": "highlightjs", "lineNumbers": [{}], "omittedLinesIcon": "<svg><use xlink:href=\"#material-design-more-vert\"/></svg>", "highlightedLines": [{"startLine": 3, "endLine": 3}], "highlightedPhrases": [{"regex":"</.*?>"}], "attributes": {"class": "block"} } } } --------------- Markdown --------------- ``` <html> <head> <title>Example Page</title> </head> <body> <p>Example content.</p> </body> </html> ``` --------------- Expected Markup --------------- <div class="code code_has-title code_has-copy-icon code_has-header code_language_html code_has-syntax-highlights code_has-line-numbers code_has-omitted-lines-icon code_has-highlighted-lines code_has-highlighted-phrases block"> <header class="code__header"> <span class="code__title">ExampleDocument.cs</span> <button class="code__copy-button" aria-label="Copy code"> <svg class="code__copy-icon"><use xlink:href="#material-design-copy"/></svg> </button> </header> <pre class="code__pre"><code class="code__code"><span class="code__line-prefix">1</span><span class="code__line"><span class="hljs-tag"><<span class="hljs-name">html</span>></span></span> <span class="code__line-prefix">2</span><span class="code__line"> <span class="hljs-tag"><<span class="hljs-name">head</span>></span></span> <span class="code__line-prefix">3</span><span class="code__line code__line_highlighted"> <span class="hljs-tag"><<span class="hljs-name">title</span>></span>Example Page<span class="code__highlighted-phrase"><span class="hljs-tag"></<span class="hljs-name">title</span>></span></span></span> <span class="code__line-prefix">4</span><span class="code__line"> <span class="code__highlighted-phrase"><span class="hljs-tag"></<span class="hljs-name">head</span>></span></span></span> <span class="code__line-prefix">5</span><span class="code__line"> <span class="hljs-tag"><<span class="hljs-name">body</span>></span></span> <span class="code__line-prefix">6</span><span class="code__line"> <span class="hljs-tag"><<span class="hljs-name">p</span>></span>Example content.<span class="code__highlighted-phrase"><span class="hljs-tag"></<span class="hljs-name">p</span>></span></span></span> <span class="code__line-prefix">7</span><span class="code__line"> <span class="code__highlighted-phrase"><span class="hljs-tag"></<span class="hljs-name">body</span>></span></span></span> <span class="code__line-prefix">8</span><span class="code__line"><span class="code__highlighted-phrase"><span class="hljs-tag"></<span class="hljs-name">html</span>></span></span></span> </code></pre> </div>defaultBlockOptionshas lower precedence than block specific options:--------------- Extra Extensions --------------- FlexiOptionsBlocks --------------- Extension Options --------------- { "flexiCodeBlocks": { "defaultBlockOptions": { "lineNumbers": [{}] } } } --------------- Markdown --------------- ``` public string ExampleFunction(string arg) { // Example comment return arg + "dummyString"; } ``` o{ "lineNumbers": [ { "startLine": 2, "startNumber": 25 } ] } ``` body { display: flex; align-items: center; font-size: 13px; } ``` --------------- Expected Markup --------------- <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_has-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code"><span class="flexi-code__line-prefix">1</span><span class="flexi-code__line">public string ExampleFunction(string arg)</span> <span class="flexi-code__line-prefix">2</span><span class="flexi-code__line">{</span> <span class="flexi-code__line-prefix">3</span><span class="flexi-code__line"> // Example comment</span> <span class="flexi-code__line-prefix">4</span><span class="flexi-code__line"> return arg + "dummyString";</span> <span class="flexi-code__line-prefix">5</span><span class="flexi-code__line">}</span> </code></pre> </div> <div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_has-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases"> <header class="flexi-code__header"> <button class="flexi-code__copy-button" aria-label="Copy code"> <svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg> </button> </header> <pre class="flexi-code__pre"><code class="flexi-code__code"><span class="flexi-code__line-prefix"><svg class="flexi-code__omitted-lines-icon" xmlns="http://www.w3.org/2000/svg" width="2px" height="10px" viewBox="0 0 2 10"><rect shape-rendering="crispEdges" width="2" height="2"/><rect shape-rendering="crispEdges" y="4" width="2" height="2"/><rect shape-rendering="crispEdges" y="8" width="2" height="2"/></svg></span><span class="flexi-code__line flexi-code__line_omitted-lines">Lines 1 to 24 omitted for brevity</span> <span class="flexi-code__line-prefix">25</span><span class="flexi-code__line">body {</span> <span class="flexi-code__line-prefix">26</span><span class="flexi-code__line"> display: flex;</span> <span class="flexi-code__line-prefix">27</span><span class="flexi-code__line"> align-items: center;</span> <span class="flexi-code__line-prefix">28</span><span class="flexi-code__line"> font-size: 13px;</span> <span class="flexi-code__line-prefix">29</span><span class="flexi-code__line">}</span> </code></pre> </div>
Mechanics
Intersecting HTML Elements
Syntax and phrase elements that intersect line elements get split. Order of elements is preserved after splitting:
--------------- Extra Extensions ---------------
FlexiOptionsBlocks
--------------- Markdown ---------------
o{
"language": "csharp",
"highlightedLines": [
{ "startLine": 3, "endLine": 3 },
{ "startLine": 8, "endLine": 8 }
],
"highlightedPhrases": [
{ "regex": "Multiline.*?1" },
{ "regex": "/.*?/", "includedMatches": [1] }
]
}
```
/*
Multiline
comment
1
*/
/*
Multiline
comment
2
*/
```
--------------- Expected Markup ---------------
<div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_language_csharp flexi-code_has-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_has-highlighted-lines flexi-code_has-highlighted-phrases">
<header class="flexi-code__header">
<button class="flexi-code__copy-button" aria-label="Copy code">
<svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg>
</button>
</header>
<pre class="flexi-code__pre"><code class="flexi-code__code"><span class="token comment">/*
<span class="flexi-code__highlighted-phrase">Multiline</span></span>
<span class="flexi-code__line flexi-code__line_highlighted"><span class="token comment"><span class="flexi-code__highlighted-phrase"> comment</span></span></span>
<span class="token comment"><span class="flexi-code__highlighted-phrase"> 1</span>
*/</span>
<span class="flexi-code__highlighted-phrase"><span class="token comment">/*
Multiline</span></span>
<span class="flexi-code__line flexi-code__line_highlighted"><span class="flexi-code__highlighted-phrase"><span class="token comment"> comment</span></span></span>
<span class="flexi-code__highlighted-phrase"><span class="token comment"> 2
*/</span></span>
</code></pre>
</div>
If a phrase element intersects a syntax element and one isn't contained by the other, the element that starts later gets split:
--------------- Extra Extensions ---------------
FlexiOptionsBlocks
--------------- Markdown ---------------
o{
"language": "csharp",
"highlightedPhrases": [
{ "regex": "comment\\s+re" },
{ "regex": "\\+ \"d" }
]
}
```
public string ExampleFunction(string arg)
{
// Example comment
return arg + "dummyString";
}
```
--------------- Expected Markup ---------------
<div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_language_csharp flexi-code_has-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_has-highlighted-phrases">
<header class="flexi-code__header">
<button class="flexi-code__copy-button" aria-label="Copy code">
<svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg>
</button>
</header>
<pre class="flexi-code__pre"><code class="flexi-code__code"><span class="token keyword">public</span> <span class="token keyword">string</span> <span class="token function">ExampleFunction</span><span class="token punctuation">(</span><span class="token keyword">string</span> arg<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token comment">// Example <span class="flexi-code__highlighted-phrase">comment</span></span><span class="flexi-code__highlighted-phrase">
<span class="token keyword">re</span></span><span class="token keyword">turn</span> arg <span class="flexi-code__highlighted-phrase"><span class="token operator">+</span> <span class="token string">"d</span></span><span class="token string">ummyString"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
Intersecting and adjacent phrases are combined:
--------------- Extra Extensions ---------------
FlexiOptionsBlocks
--------------- Markdown ---------------
o{
"highlightedPhrases": [
{ "regex": "comment\\s+re" },
{ "regex": "(return )(arg)" },
{ "regex": "return" },
{ "regex": "rg \\+" }
]
}
```
public string ExampleFunction(string arg)
{
// Example comment
return arg + "dummyString";
}
```
--------------- Expected Markup ---------------
<div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_has-highlighted-phrases">
<header class="flexi-code__header">
<button class="flexi-code__copy-button" aria-label="Copy code">
<svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg>
</button>
</header>
<pre class="flexi-code__pre"><code class="flexi-code__code">public string ExampleFunction(string arg)
{
// Example <span class="flexi-code__highlighted-phrase">comment
return arg +</span> "dummyString";
}
</code></pre>
</div>
Contained elements never get split:
--------------- Extra Extensions ---------------
FlexiOptionsBlocks
--------------- Markdown ---------------
o{
"language": "csharp",
"highlightedPhrases": [
{ "regex": "string ExampleFunction" },
{ "regex": "return" },
{ "regex": "(\"dum)myStr(ing\")" }
]
}
```
public string ExampleFunction(string arg)
{
// Example comment
return arg + "dummyString";
}
```
--------------- Expected Markup ---------------
<div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_language_csharp flexi-code_has-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_has-highlighted-phrases">
<header class="flexi-code__header">
<button class="flexi-code__copy-button" aria-label="Copy code">
<svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg>
</button>
</header>
<pre class="flexi-code__pre"><code class="flexi-code__code"><span class="token keyword">public</span> <span class="flexi-code__highlighted-phrase"><span class="token keyword">string</span> <span class="token function">ExampleFunction</span></span><span class="token punctuation">(</span><span class="token keyword">string</span> arg<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token comment">// Example comment</span>
<span class="flexi-code__highlighted-phrase"><span class="token keyword">return</span></span> arg <span class="token operator">+</span> <span class="flexi-code__highlighted-phrase"><span class="token string">"dum</span></span><span class="token string">myStr<span class="flexi-code__highlighted-phrase">ing"</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
HTML Encoding
If syntax highlighting is enabled, the chosen syntax highlighter performs the encoding. Prism encodes '<' and '&' characters:
--------------- Extra Extensions ---------------
FlexiOptionsBlocks
--------------- Markdown ---------------
o{
"language": "html"
}
```
<div class="my-class">&</div>
```
--------------- Expected Markup ---------------
<div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_language_html flexi-code_has-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases">
<header class="flexi-code__header">
<button class="flexi-code__copy-button" aria-label="Copy code">
<svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg>
</button>
</header>
<pre class="flexi-code__pre"><code class="flexi-code__code"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>my-class<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>&<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
</code></pre>
</div>
HighlightJS encodes '<', '&' and '>' characters:
--------------- Extra Extensions ---------------
FlexiOptionsBlocks
--------------- Markdown ---------------
o{
"language": "html",
"syntaxHighlighter": "highlightjs"
}
```
<div class="my-class">&</div>
```
--------------- Expected Markup ---------------
<div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_language_html flexi-code_has-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases">
<header class="flexi-code__header">
<button class="flexi-code__copy-button" aria-label="Copy code">
<svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg>
</button>
</header>
<pre class="flexi-code__pre"><code class="flexi-code__code"><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"my-class"</span>></span>&<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
</code></pre>
</div>
If syntax highlighting is disabled, '<', '&', '"", and '>' characters are encoded:
--------------- Extra Extensions ---------------
FlexiOptionsBlocks
--------------- Markdown ---------------
```
<div class="my-class">&</div>
```
--------------- Expected Markup ---------------
<div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_no-highlighted-phrases">
<header class="flexi-code__header">
<button class="flexi-code__copy-button" aria-label="Copy code">
<svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg>
</button>
</header>
<pre class="flexi-code__pre"><code class="flexi-code__code"><div class="my-class">&</div>
</code></pre>
</div>
Encoding does not affect highlighted phrases (regex expressions are evaluated before encoding):
--------------- Extra Extensions ---------------
FlexiOptionsBlocks
--------------- Markdown ---------------
o{
"highlightedPhrases": [{ "regex": "div" }]
}
```
<div class="my-class">&</div>
```
--------------- Expected Markup ---------------
<div class="flexi-code flexi-code_no-title flexi-code_has-copy-icon flexi-code_has-header flexi-code_no-syntax-highlights flexi-code_no-line-numbers flexi-code_has-omitted-lines-icon flexi-code_no-highlighted-lines flexi-code_has-highlighted-phrases">
<header class="flexi-code__header">
<button class="flexi-code__copy-button" aria-label="Copy code">
<svg class="flexi-code__copy-icon" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18"><path fill="none" d="M0,0h18v18H0V0z"/><path d="M12,1H2v13h2V3h8V1z M12,4l4,4v9H5V4H12z M11,9h4l-4-4V9z"/></svg>
</button>
</header>
<pre class="flexi-code__pre"><code class="flexi-code__code"><<span class="flexi-code__highlighted-phrase">div</span> class="my-class">&</<span class="flexi-code__highlighted-phrase">div</span>>
</code></pre>
</div>
Incomplete Features
Integrate Try.Net - https://dotnet.microsoft.com/platform/try-dotnet.