diff --git a/lib/md038.js b/lib/md038.js index bf8fa39e..25314197 100644 --- a/lib/md038.js +++ b/lib/md038.js @@ -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); } } diff --git a/lib/shared.js b/lib/shared.js index cbd5e434..cd10c760 100644 --- a/lib/shared.js +++ b/lib/shared.js @@ -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); } }); }); diff --git a/test/detailed-results-MD031-MD040.md b/test/detailed-results-MD031-MD040.md index c616f484..3bb24faa 100644 --- a/test/detailed-results-MD031-MD040.md +++ b/test/detailed-results-MD031-MD040.md @@ -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. diff --git a/test/detailed-results-MD031-MD040.results.json b/test/detailed-results-MD031-MD040.results.json index 1ff00649..d1fb85ac 100644 --- a/test/detailed-results-MD031-MD040.results.json +++ b/test/detailed-results-MD031-MD040.results.json @@ -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" ], diff --git a/test/line-breaks-inside-code-spans.md b/test/line-breaks-inside-code-spans.md new file mode 100644 index 00000000..850240c0 --- /dev/null +++ b/test/line-breaks-inside-code-spans.md @@ -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.