Handle multi-line inline code spans better (fixes #130).

This commit is contained in:
David Anson 2018-07-15 23:05:18 -07:00
parent 6afd61ed66
commit 4865301ce9
5 changed files with 115 additions and 13 deletions

View file

@ -4,28 +4,46 @@
const shared = require("./shared");
const inlineCodeSpansRe = /(?:^|[^\\])((`+)((?:.*?[^`])|)\2(?!`))/g;
const inlineCodeSpansRe = /(?:^|[^\\])((`+)((?:[\s\S]*?[^`])|)\2(?!`))/g;
module.exports = {
"names": [ "MD038", "no-space-in-code" ],
"description": "Spaces inside code span elements",
"tags": [ "whitespace", "code" ],
"function": function MD038(params, onError) {
let lastParent = null;
shared.forEachInlineChild(params, "code_inline",
function forToken(token) {
const line = params.lines[token.lineNumber - 1];
let match = null;
while ((match = inlineCodeSpansRe.exec(line)) !== null) {
function forToken(token, parent) {
if (lastParent !== parent) {
lastParent = parent;
inlineCodeSpansRe.lastIndex = 0;
}
const match = inlineCodeSpansRe.exec(parent.content);
const content = match[3];
const leftError = /^\s([^`]|$)/.test(content);
const rightError = /[^`]\s$/.test(content);
if (leftError || rightError) {
const inlineCodeSpan = match[1];
const content = match[3];
const length = inlineCodeSpan.length;
const column = match.index + 1 + (match[0].length - length);
const range = [ column, length ];
if (/^\s([^`]|$)/.test(content)) {
const leftContent = parent.content.substr(0,
match.index + (match[0].length - inlineCodeSpan.length));
const leftContentLines = leftContent.split(shared.newLineRe);
const inlineCodeSpanLines = inlineCodeSpan.split(shared.newLineRe);
let range = [
leftContentLines[leftContentLines.length - 1].length + 1,
inlineCodeSpanLines[0].length
];
if (leftError) {
shared.addErrorContext(onError, token.lineNumber,
inlineCodeSpan, true, false, range);
} else if (/[^`]\s$/.test(content)) {
shared.addErrorContext(onError, token.lineNumber,
} else {
if (inlineCodeSpanLines.length > 1) {
range = [
1,
inlineCodeSpanLines[inlineCodeSpanLines.length - 1].length
];
}
shared.addErrorContext(onError,
token.lineNumber + content.split(shared.newLineRe).length - 1,
inlineCodeSpan, false, true, range);
}
}

View file

@ -235,7 +235,7 @@ function forEachInlineChild(params, type, callback) {
filterTokens(params, "inline", function forToken(token) {
token.children.forEach(function forChild(child) {
if (child.type === type) {
callback(child);
callback(child, token);
}
});
});

View file

@ -33,3 +33,13 @@ some *space* in *some * emphasis
some *space* in **some ** emphasis
some _space_ in _ some_ emphasis
some __space__ in __ some __ emphasis
Text
text ` code
span` text
text.
Text
text `code
span ` text
text.

View file

@ -151,6 +151,22 @@
"errorContext": "``embedded backtick` ``",
"errorRange": [ 1, 24 ]
},
{
"lineNumber": 38,
"ruleNames": [ "MD038", "no-space-in-code" ],
"ruleDescription": "Spaces inside code span elements",
"errorDetail": null,
"errorContext": "` code\nspan`",
"errorRange": [ 6, 6 ]
},
{
"lineNumber": 44,
"ruleNames": [ "MD038", "no-space-in-code" ],
"ruleDescription": "Spaces inside code span elements",
"errorDetail": null,
"errorContext": "`code\nspan `",
"errorRange": [ 1, 7 ]
},
{
"lineNumber": 19,
"ruleNames": [ "MD039", "no-space-in-links" ],

View file

@ -0,0 +1,58 @@
# Line breaks inside code spans
Text `code
span` text.
Text `code
span` text `code
span` text.
Text `code
span` text `code
span` text `code
span` text.
Text `code
span
code
span` text.
Text `code
span` text `code span`
text `code span` text.
Text `code
span` text `code span` text
`code span` text.
`code
span` `span`
`span`
Text
text ` code {MD038}
span` text
text.
Text
text `code
span ` text {MD038}
text.
Text
text `code
span code
span` text
text.
Text
text ` code {MD038}
span code
span` text
text.
Text
text `code
span code
span ` text {MD038}
text.