Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: renderer.code includes space at beginning of each line of code #1645

Merged
merged 19 commits into from May 2, 2020
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/Tokenizer.js
Expand Up @@ -3,7 +3,8 @@ const {
rtrim,
splitCells,
escape,
findClosingBracket
findClosingBracket,
indentCodeCompensation
} = require('./helpers.js');

function outputLink(cap, link, raw) {
Expand Down Expand Up @@ -77,11 +78,14 @@ module.exports = class Tokenizer {
fences(src) {
const cap = this.rules.block.fences.exec(src);
if (cap) {
const raw = cap[0];
const text = indentCodeCompensation(raw, cap[3] || '');

return {
type: 'code',
raw: cap[0],
raw,
lang: cap[2] ? cap[2].trim() : cap[2],
text: cap[3] || ''
text
};
}
}
Expand Down
35 changes: 34 additions & 1 deletion src/helpers.js
Expand Up @@ -228,6 +228,38 @@ function checkSanitizeDeprecation(opt) {
}
}

function indentCodeCompensation(raw, text) {
UziTech marked this conversation as resolved.
Show resolved Hide resolved
if (raw === undefined) {
return text;
}

const matchIndentToCode = raw.match(/^(\s+)(?:```)/);

if (matchIndentToCode === null) {
return text;
}

const [indentToCode] = matchIndentToCode.reverse();
UziTech marked this conversation as resolved.
Show resolved Hide resolved

return text
.split('\n')
.map(node => {
const matchIndentInNode = node.match(/^\s+/);
if (matchIndentInNode === null) {
return node;
}

const [indentInNode] = matchIndentInNode;

if (indentInNode.length >= indentToCode.length) {
return node.slice(indentToCode.length);
}

return node;
})
.join('\n');
}

module.exports = {
escape,
unescape,
Expand All @@ -239,5 +271,6 @@ module.exports = {
splitCells,
rtrim,
findClosingBracket,
checkSanitizeDeprecation
checkSanitizeDeprecation,
indentCodeCompensation
};
13 changes: 12 additions & 1 deletion test/helpers/helpers.js
@@ -1,5 +1,6 @@
const marked = require('../../src/marked.js');
const htmlDiffer = require('./html-differ.js');
const assert = require('assert').strict;
UziTech marked this conversation as resolved.
Show resolved Hide resolved

beforeEach(() => {
marked.setOptions(marked.getDefaults());
Expand Down Expand Up @@ -37,6 +38,16 @@ beforeEach(() => {
return result;
}
};
}
},
toRenderExact: () => ({
compare: async(spec, expected) => {
const result = {};
const actual = marked(spec.markdown, spec.options);

result.pass = assert.deepStrictEqual(expected, actual) === undefined;
UziTech marked this conversation as resolved.
Show resolved Hide resolved
UziTech marked this conversation as resolved.
Show resolved Hide resolved

return result;
}
})
});
});
6 changes: 6 additions & 0 deletions test/specs/new/code_compensation_indent.html
@@ -0,0 +1,6 @@
<p>This is some text.</p>
<ol>
<li><p>This is a list element.</p>
<pre><code>const x = 5;
const y = x + 5;</code></pre></li>
</ol>
11 changes: 11 additions & 0 deletions test/specs/new/code_compensation_indent.md
@@ -0,0 +1,11 @@
---
renderExact: true
---
This is some text.

1. This is a list element.

```
const x = 5;
const y = x + 5;
```
5 changes: 5 additions & 0 deletions test/specs/run-spec.js
Expand Up @@ -16,17 +16,22 @@ function runSpecs(title, dir, showCompletionTable, options) {
spec.options = Object.assign({}, options, (spec.options || {}));
const example = (spec.example ? ' example ' + spec.example : '');
const passFail = (spec.shouldFail ? 'fail' : 'pass');

if (typeof spec.options.silent === 'undefined') {
spec.options.silent = true;
}

if (spec.options.sanitizer) {
// eslint-disable-next-line no-eval
spec.options.sanitizer = eval(spec.options.sanitizer);
}

(spec.only ? fit : (spec.skip ? xit : it))('should ' + passFail + example, async() => {
const before = process.hrtime();
if (spec.shouldFail) {
await expectAsync(spec).not.toRender(spec.html);
} else if (spec.options.renderExact) {
await expectAsync(spec).toRenderExact(spec.html);
} else {
await expectAsync(spec).toRender(spec.html);
}
Expand Down