Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions asset/css/markbind.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,36 @@ pre > code.hljs {
counter-reset: line;
}

pre > code.hljs[heading] {
border-top-right-radius: 0;
}

.code-block {
position: relative;
}

.code-block-heading {
background-color: #f2f2ff;
border-radius: 6px 6px 0 0;
color: #8787a5;
float: right;
font-size: 85%;
line-height: 1;
max-width: 85%;
overflow-wrap: break-word;
padding: 0.25em 0.4em;
text-align: right;
}

.code-block-content {
clear: both;
display: block;
}

code > span.highlighted {
background: lavender;
}

kbd {
background-color: #fafbfc;
border: 1px solid #c6cbd1;
Expand Down
92 changes: 86 additions & 6 deletions docs/userGuide/syntax/code.mbdf
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
## Code

MarkBind can provide syntax coloring and line numbers for a code block (aka _Fenced Code Blocks_).
#### Fenced Code
MarkBind provides several features, some of which are added on top of the existing functionality of Markdown's _fenced code blocks_.

<small>More info: https://www.markdownguide.org/extended-syntax#fenced-code-blocks</small>


Features:
- Syntax coloring
- Line numbering
- Line highlighting
- Code block headers

##### Syntax coloring
To enable syntax coloring, specify a language next to the backticks before the fenced code block.
<span id="main-example">
<include src="outputBox.md" boilerplate >
<span id="code">

````
```` {.no-line-numbers}
```xml
<foo>
<bar type="name">goo</bar>
Expand All @@ -24,12 +37,13 @@ MarkBind can provide syntax coloring and line numbers for a code block (aka _Fen
</include>
</span>

As seen above, line numbers are automatically provided for a code block. To hide line numbers, add the class `no-line-numbers ` to the code block like below:
##### Line numbering
Line numbers are automatically provided by default. To hide line numbers, add the class `no-line-numbers ` to the code block as below

<include src="outputBox.md" boilerplate >
<span id="code">

````
```` {.no-line-numbers}
```xml {.no-line-numbers}
<foo>
<bar type="name">goo</bar>
Expand All @@ -47,9 +61,75 @@ As seen above, line numbers are automatically provided for a code block. To hide
</span>
</include>

<small>More info: https://www.markdownguide.org/extended-syntax#fenced-code-blocks</small>
##### Line highlighting
To highlight lines, add the attribute `highlight-lines` with the line numbers as value, as shown below. You can specify ranges or individual line numbers.

<include src="outputBox.md" boilerplate >
<span id="code">

```` {.no-line-numbers}
```java {highlight-lines="2,4,6-8"}
import java.util.List;

public class Inventory {
private List<Item> items;

public int getItemCount(){
return items.size();
}

//...
}
```
````
</span>
<span id="output">

```java {highlight-lines="2,4,6-8"}
import java.util.List;

public class Inventory {
private List<Item> items;

public int getItemCount(){
return items.size();
}

//...
}
```
</span>
</include>

##### Heading
To add a heading, add the attribute `heading` with the heading text as the value, as shown below.

<include src="outputBox.md" boilerplate >
<span id="code">

```` {.no-line-numbers}
```xml {heading="Heading title"}
<foo>
<bar type="name">goo</bar>
</foo>
```
````
</span>
<span id="output">

```xml {heading="Heading title"}
<foo>
<bar type="name">goo</bar>
</foo>
```
</span>
</include>

#### Inline Code
##### Syntax coloring


In addition, MarkBind can apply syntax-coloring on inline code too.
MarkBind can apply syntax-coloring on inline code too.

<include src="outputBox.md" boilerplate >
<span id="code">
Expand Down
51 changes: 45 additions & 6 deletions src/lib/markbind/src/lib/markdown-it/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,57 @@ markdownIt.renderer.rules.fence = (tokens, idx, options, env, slf) => {
if (!highlighted) {
lines = markdownIt.utils.escapeHtml(str).split('\n');
}

const highlightLinesInput = token.attrGet('highlight-lines');
let lineNumbersAndRanges = [];
if (highlightLinesInput) {
// example input format: "1,4-7,8,11-55"
// output: [[1],[4,7],[8],[11,55]]
// the output is an array contaning either single line numbers [lineNum] or ranges [start, end]
// ',' delimits either single line numbers (eg: 1) or ranges (eg: 4-7)
highlightLines = highlightLinesInput.split(',');
// if it's the single number, it will just be parsed as an int, (eg: ['1'] --> [1] )
// if it's a range, it will be parsed as as an array of two ints (eg: ['4-7'] --> [4,6])
lineNumbersAndRanges = highlightLines.map(elem => elem.split('-').map(lineNumber => parseInt(lineNumber, 10)));
}

lines.pop(); // last line is always a single '\n' newline, so we remove it

/* wrap all lines with <span> so we can number them
if a line is empty we put a 0 width non breaking space
*/
str = lines.map(line => `<span>${line || '&#x200B;'}</span>`).join('');
// wrap all lines with <span> so we can number them
str = lines.map((line, index) => {
// if a line is empty we put a 0 width non breaking space
const content = line || '&#x200B;';
const currentLineNumber = index + 1;
// check if there is at least one range or line number that matches the current line number
// Note: The algorithm is based off markdown-it-highlight-lines (https://github.com/egoist/markdown-it-highlight-lines/blob/master/src/index.js)
// This is an O(n^2) solution wrt to the number of lines
// I opt to use this approach because it's simple, and it is unlikely that the number of elements in `lineNumbersAndRanges` will be large
// There is possible room for improvement for a more efficient algo that is O(n).
const inRange = lineNumbersAndRanges.some(([start, end]) => {
if (start && end) {
return currentLineNumber >= start && currentLineNumber <= end;
}
return currentLineNumber === start;
});
if (inRange) {
return `<span class="highlighted">${content}</span>`;
}
return `<span>${content}</span>`;
}).join('');

token.attrJoin('class', 'hljs');
if (highlighted) {
token.attrJoin('class', lang);
}
return `<pre><code ${slf.renderAttrs(token)}>${str}</code></pre>`;

const heading = token.attrGet('heading');
const codeBlockContent = `<pre><code ${slf.renderAttrs(token)}>${str}</code></pre>`;
if (heading) {
return '<div class="code-block">'
+ `<div class="code-block-heading"><span>${heading}</span></div>`
+ `<div class="code-block-content">${codeBlockContent}</div>`
+ '</div>';
}
return codeBlockContent;
};

// highlight inline code
Expand Down
30 changes: 30 additions & 0 deletions test/functional/test_site/expected/markbind/css/markbind.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,36 @@ pre > code.hljs {
counter-reset: line;
}

pre > code.hljs[heading] {
border-top-right-radius: 0;
}

.code-block {
position: relative;
}

.code-block-heading {
background-color: #f2f2ff;
border-radius: 6px 6px 0 0;
color: #8787a5;
float: right;
font-size: 85%;
line-height: 1;
max-width: 85%;
overflow-wrap: break-word;
padding: 0.25em 0.4em;
text-align: right;
}

.code-block-content {
clear: both;
display: block;
}

code > span.highlighted {
background: lavender;
}

kbd {
background-color: #fafbfc;
border: 1px solid #c6cbd1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,36 @@ pre > code.hljs {
counter-reset: line;
}

pre > code.hljs[heading] {
border-top-right-radius: 0;
}

.code-block {
position: relative;
}

.code-block-heading {
background-color: #f2f2ff;
border-radius: 6px 6px 0 0;
color: #8787a5;
float: right;
font-size: 85%;
line-height: 1;
max-width: 85%;
overflow-wrap: break-word;
padding: 0.25em 0.4em;
text-align: right;
}

.code-block-content {
clear: both;
display: block;
}

code > span.highlighted {
background: lavender;
}

kbd {
background-color: #fafbfc;
border: 1px solid #c6cbd1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,36 @@ pre > code.hljs {
counter-reset: line;
}

pre > code.hljs[heading] {
border-top-right-radius: 0;
}

.code-block {
position: relative;
}

.code-block-heading {
background-color: #f2f2ff;
border-radius: 6px 6px 0 0;
color: #8787a5;
float: right;
font-size: 85%;
line-height: 1;
max-width: 85%;
overflow-wrap: break-word;
padding: 0.25em 0.4em;
text-align: right;
}

.code-block-content {
clear: both;
display: block;
}

code > span.highlighted {
background: lavender;
}

kbd {
background-color: #fafbfc;
border: 1px solid #c6cbd1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,36 @@ pre > code.hljs {
counter-reset: line;
}

pre > code.hljs[heading] {
border-top-right-radius: 0;
}

.code-block {
position: relative;
}

.code-block-heading {
background-color: #f2f2ff;
border-radius: 6px 6px 0 0;
color: #8787a5;
float: right;
font-size: 85%;
line-height: 1;
max-width: 85%;
overflow-wrap: break-word;
padding: 0.25em 0.4em;
text-align: right;
}

.code-block-content {
clear: both;
display: block;
}

code > span.highlighted {
background: lavender;
}

kbd {
background-color: #fafbfc;
border: 1px solid #c6cbd1;
Expand Down
Loading