diff --git a/docs/userGuide/syntax/code.mbdf b/docs/userGuide/syntax/code.mbdf
index e4aaef01f2..9f9278ce3e 100644
--- a/docs/userGuide/syntax/code.mbdf
+++ b/docs/userGuide/syntax/code.mbdf
@@ -38,7 +38,7 @@ To enable syntax coloring, specify a language next to the backticks before the f
##### 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
+Line numbers are provided by default. To hide line numbers, add the class `no-line-numbers` to the code block as below
@@ -61,6 +61,30 @@ Line numbers are automatically provided by default. To hide line numbers, add th
+You can have your line numbers start with a value other than `1` with the `start-from` attribute.
+
+
+
+
+```` {.no-line-numbers}
+```js {start-from=6}
+function add(a, b) {
+ return a + b;
+}
+```
+````
+
+
+
+```js {start-from=6}
+function add(a, b) {
+ return a + b;
+}
+```
+
+
+
+
##### 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.
diff --git a/src/lib/markbind/src/lib/markdown-it/index.js b/src/lib/markbind/src/lib/markdown-it/index.js
index d89a5e31cb..1ecc0f6c09 100644
--- a/src/lib/markbind/src/lib/markdown-it/index.js
+++ b/src/lib/markbind/src/lib/markdown-it/index.js
@@ -30,6 +30,18 @@ markdownIt.renderer.rules.table_close = (tokens, idx) => {
return '';
};
+function getAttributeAndDelete(token, attr) {
+ const index = token.attrIndex(attr);
+ if (index === -1) {
+ return undefined;
+ }
+ // tokens are stored as an array of two-element-arrays:
+ // e.g. [ ['highlight-lines', '1,2,3'], ['start-from', '1'] ]
+ const value = token.attrs[index][1];
+ token.attrs.splice(index, 1);
+ return value;
+}
+
// syntax highlight code fences and add line numbers
markdownIt.renderer.rules.fence = (tokens, idx, options, env, slf) => {
const token = tokens[idx];
@@ -64,18 +76,31 @@ markdownIt.renderer.rules.fence = (tokens, idx, options, env, slf) => {
if (!highlighted) {
lines = markdownIt.utils.escapeHtml(str).split('\n');
}
+
+ const startFromOneBased = Math.max(1, parseInt(getAttributeAndDelete(token, 'start-from'), 10) || 1);
+ const startFromZeroBased = startFromOneBased - 1;
+
+ if (startFromOneBased > 1) {
+ // counter is incremented on each span, so we need to subtract 1
+ token.attrJoin('style', `counter-reset: line ${startFromZeroBased};`);
+ }
- const highlightLinesInput = token.attrGet('highlight-lines');
+ const highlightLinesInput = getAttributeAndDelete(token, '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(',');
+ const 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)));
+ function parseAndZeroBaseLineNumber(numberString) {
+ // authors provide line numbers to highlight based on the 'start-from' attribute if it exists
+ // so we need to shift them all back down to start at 0
+ return parseInt(numberString, 10) - startFromZeroBased;
+ }
+ lineNumbersAndRanges = highlightLines.map(elem => elem.split('-').map(parseAndZeroBaseLineNumber));
}
lines.pop(); // last line is always a single '\n' newline, so we remove it
diff --git a/test/functional/test_site/expected/testCodeBlocks.html b/test/functional/test_site/expected/testCodeBlocks.html
index 46309043f9..46a7829fc7 100644
--- a/test/functional/test_site/expected/testCodeBlocks.html
+++ b/test/functional/test_site/expected/testCodeBlocks.html
@@ -32,6 +32,12 @@
functionfourEmptyLinesBelow() {} // four empty lines above
hljs span spanning multiple lines
*****-----
+
start-from attr causes inline style to be set
+
*****-----
+
highlight-lines attr causes corresponding lines to have 'highlighted' class