Skip to content

Commit

Permalink
Add option emptyLines
Browse files Browse the repository at this point in the history
  • Loading branch information
Yang Zhao committed Sep 2, 2020
1 parent 58b6945 commit 6fbf581
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 4 deletions.
6 changes: 4 additions & 2 deletions lib/configs/default.js
Expand Up @@ -22,7 +22,8 @@ export default {
//
highlight: null,

maxNesting: 20 // Internal protection, recursion limit
maxNesting: 20, // Internal protection, recursion limit
emptyLines: false // Preserve empty lines with empty <p> tag
},

components: {
Expand All @@ -36,7 +37,8 @@ export default {
'smartquotes',
'references',
'abbr2',
'footnote_tail'
'footnote_tail',
'empty_lines'
]
},

Expand Down
3 changes: 2 additions & 1 deletion lib/configs/full.js
Expand Up @@ -22,7 +22,8 @@ export default {
//
highlight: null,

maxNesting: 20 // Internal protection, recursion limit
maxNesting: 20, // Internal protection, recursion limit
emptyLines: false // Preserve empty lines with empty <p> tag
},

components: {
Expand Down
11 changes: 10 additions & 1 deletion lib/parser_block.js
Expand Up @@ -65,7 +65,16 @@ ParserBlock.prototype.tokenize = function (state, startLine, endLine) {
var ok, i;

while (line < endLine) {
state.line = line = state.skipEmptyLines(line);
var newLine = state.skipEmptyLines(line);
// save the emtpy lines info into state.env.emptyLines
if (state.options.emptyLines === true && newLine > line) {
state.env.emptyLines = state.env.emptyLines || {};
state.env.emptyLines[line] = newLine - line;
}
state.line = line = newLine;
if (line >= endLine) {
break;
}
if (line >= endLine) {
break;
}
Expand Down
2 changes: 2 additions & 0 deletions lib/parser_core.js
Expand Up @@ -8,6 +8,7 @@ import footnote_tail from './rules_core/footnote_tail';
import abbr2 from './rules_core/abbr2';
import replacements from './rules_core/replacements';
import smartquotes from './rules_core/smartquotes';
import empty_lines from "./rules_core/empty_lines";

/**
* Core parser `rules`
Expand All @@ -22,6 +23,7 @@ var _rules = [
[ 'abbr2', abbr2 ],
[ 'replacements', replacements ],
[ 'smartquotes', smartquotes ],
[ 'empty_lines', empty_lines ],
];

/**
Expand Down
60 changes: 60 additions & 0 deletions lib/rules_core/empty_lines.js
@@ -0,0 +1,60 @@
// Transform empty lines into empty <p> tags
// empty lines data comes from state.env.emptyLines,

export default function empty_lines_block(state) {
var i, ln;
var emptyLines = state.env.emptyLines;
if (!emptyLines || state.options.emptyLines !== true) {
return;
}
var tokens = state.tokens;
var pendingTokens = [];
var lastVisitedIndex = 0;
for (var lineNumber in emptyLines) {
for (i = lastVisitedIndex; i < tokens.length; i++) {
var token = tokens[i];
ln = Number(lineNumber);
// find the first "paragraph" that after the current empty lines
if (
token.type === 'paragraph_open' &&
token.lines &&
token.lines[0] >= ln
) {
// push the index info of the found "paragraph"
pendingTokens.push({
index: i,
lineNumber: ln,
level: token.level
});
lastVisitedIndex = ln;
break;
}
}
}

// insert the empty line from last to first
while (pendingTokens.length > 0) {
var t = pendingTokens.pop();
var idx = t.index, lvl = t.level;
ln = t.lineNumber;
for (i = 0; i < emptyLines[ln] - 1; i++) {
tokens.splice(
idx,
0,
{
type: 'paragraph_open',
tight: false,
lines: [ln + i, ln + i + emptyLines[ln]],
level: lvl
},
{
type: 'paragraph_close',
tight: false,
level: lvl
}
);
}
}

state.tokens = tokens;
};
36 changes: 36 additions & 0 deletions test/empty_lines.js
@@ -0,0 +1,36 @@

import assert from 'assert';
import { Remarkable } from '../lib/index';

describe('Test empty lines plugin', function() {
it('should render with empty lines when enabled', function() {
[
['', ''],
['abc\n\ndef\n', '<p>abc</p>\n<p>def</p>\n'],
['abc\n\n\ndef\n', '<p>abc</p>\n<p>def</p>\n'],
['abc\n\n\n\ndef\n\n\n\nghi\n', '<p>abc</p>\n<p></p>\n<p>def</p>\n<p></p>\n<p>ghi</p>\n'],
['line1\n\n\n\nline3\n', '<p>line1</p>\n<p></p>\n<p>line3</p>\n'],
['* line1\n* line2\n\n\nline4\n', '<ul>\n<li>line1</li>\n<li>line2</li>\n</ul>\n<p>line4</p>\n']
].forEach(function(data) {
var [text, expected] = data;
var md = new Remarkable('full', { emptyLines: true });
var rendered = md.render(text);
assert.strictEqual(rendered, expected);
});
});

it('should render without empty lines when disabled', function() {
[
['', ''],
['abc\n\ndef\n', '<p>abc</p>\n<p>def</p>\n'],
['abc\n\n\ndef\n', '<p>abc</p>\n<p>def</p>\n'],
['line1\n\n\n\nline3\n', '<p>line1</p>\n<p>line3</p>\n'],
['* line1\n* line2\n\n\n\n\n\n\nline4\n', '<ul>\n<li>line1</li>\n<li>line2</li>\n</ul>\n<p>line4</p>\n']
].forEach(function(data) {
var [text, expected] = data;
var md = new Remarkable('full');
var rendered = md.render(text);
assert.strictEqual(rendered, expected);
});
});
});

0 comments on commit 6fbf581

Please sign in to comment.