Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@
"textlint"
],
"devDependencies": {
"eslint": "6.0.1",
"textlint-scripts": "^2.1.0"
"@types/structured-source": "^3.0.0",
"eslint": "6.5.1",
"textlint-scripts": "^2.1.0",
"textlint-plugin-asciidoctor": "^1.0.3"
},
"peerDependencies": {
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0"
},
"dependencies": {
"structured-source": "^3.0.2"
}
}
43 changes: 29 additions & 14 deletions src/textlint-rule-eslint.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// LICENSE : MIT
"use strict";
const CLIEngine = require("eslint").CLIEngine;
const path = require("path");
const Source = require("structured-source");
const CLIEngine = require("eslint").CLIEngine;
const defaultOptions = {
// path to .eslintrc file
"configFile": null,
Expand Down Expand Up @@ -37,7 +38,7 @@ const reporter = (context, options) => {
}
const raw = getSource(node);
const code = getUntrimmedCode(node, raw);

const source = new Source(code);
const resultLinting = engine.executeOnText(code, node.lang);
if (resultLinting.errorCount === 0) {
return;
Expand All @@ -54,24 +55,33 @@ const reporter = (context, options) => {
ESLint message line and column start with 1
*/
if (options.ignoreParsingErrors && message.message.includes("Parsing error")) {
return;
return;
}

const prefix = message.ruleId ? `${message.ruleId}: ` : "";
if (message.fix) {
const paddingIndex = raw.indexOf(code);
const fixedRange = message.fix.range;
const fixedText = message.fix.text;
const fixedWithPadding = [fixedRange[0] + paddingIndex, fixedRange[1] + paddingIndex];
report(node, new RuleError(`${prefix}${message.message}`, {
const sourceBlockDiffIndex = (raw !== node.value) ? raw.indexOf(code) : 0;
const fixedWithPadding = [fixedRange[0] + sourceBlockDiffIndex, fixedRange[1] + sourceBlockDiffIndex];
const index = source.positionToIndex({
line: message.line,
column: message.column - 1,
column: message.column
});
const adjustedIndex = index + sourceBlockDiffIndex - 1;
report(node, new RuleError(`${prefix}${message.message}`, {
index: adjustedIndex,
fix: fixer.replaceTextRange(fixedWithPadding, fixedText)
}));
} else {
report(node, new RuleError(`${prefix}${message.message}`, {
const sourceBlockDiffIndex = (raw !== node.value) ? raw.indexOf(code) : 0;
const index = source.positionToIndex({
line: message.line,
column: message.column - 1
column: message.column
});
const adjustedIndex = index + sourceBlockDiffIndex - 1;
report(node, new RuleError(`${prefix}${message.message}`, {
index: adjustedIndex
}));
}

Expand All @@ -82,7 +92,7 @@ const reporter = (context, options) => {
};

/**
* get actual code value from CodeBlock node
* [Markdown] get actual code value from CodeBlock node
* @param {Object} node
* @param {string} raw raw value include CodeBlock syntax
* @returns {string}
Expand All @@ -91,18 +101,23 @@ function getUntrimmedCode(node, raw) {
if (node.type !== "CodeBlock") {
return node.value
}

// Space indented CodeBlock that has not lang
if (!node.lang) {
return node.value;
}

// If it is not markdown codeBlock, just use node.value
if (!(raw.startsWith("```") && raw.endsWith("```"))) {
if (node.value.endsWith("\n")) {
return node.value
}
return node.value + "\n";
}
// Markdown(remark) specific hack
// https://github.com/wooorm/remark/issues/207#issuecomment-244620590
const lines = raw.split("\n");

// code lines without the first line and the last line
const codeLines = lines.slice(1, lines.length - 1);

// add last new line
// \n```
return codeLines.join("\n") + "\n";
Expand All @@ -111,4 +126,4 @@ function getUntrimmedCode(node, raw) {
module.exports = {
linter: reporter,
fixer: reporter
};
};
68 changes: 68 additions & 0 deletions test/asciidoc.disabled
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// LICENSE : MIT
"use strict";
import rule from "../src/textlint-rule-eslint";
const path = require("path");
const TextLintTester = require("textlint-tester");
const asciidoctorPlugin = require("textlint-plugin-asciidoctor");
const tester = new TextLintTester();
const configFilePath = path.join(__dirname, "fixtures/style.eslintconfig.js");
tester.run("textlint-rule-eslint with asciidoctor plugin", {
plugins: [
{
pluginId: "asciidoc",
plugin: asciidoctorPlugin,
}
],
rules: [
{
ruleId: "eslint",
rule: rule,
options: {
configFile: configFilePath
}
}
]
}, {
valid: [
{
text: `
[role="executable"]
[source,javascript]
.thenコード例
----
var promise = new Promise(function(resolve, reject) {
resolve("thenに渡す値");
});
promise.then(function(value) {
console.log(value);
}, function(error) {
console.error(error);
});
----
`,
ext: ".adoc",

}
],
invalid: [
{
text: `
[source,javascript]
----
var a = 1
----
`,
output: `
[source,javascript]
----
var a = 1;
----
`,
ext: ".adoc",
errors: [{
index: 35
}]
}
]

});
1 change: 1 addition & 0 deletions test/mocha.opts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--require textlint-scripts/register
84 changes: 55 additions & 29 deletions test/textlint-rule-eslint-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// LICENSE : MIT
"use strict";
import rule from "../src/textlint-rule-eslint";

const path = require("path");
const TextLintTester = require("textlint-tester");
const tester = new TextLintTester();
Expand All @@ -17,35 +18,35 @@ tester.run("textlint-rule-eslint", rule, {
},
{
text: "```js\n" +
"var a = 1;\n" +
"```",
"var a = 1;\n" +
"```",
options: {
configFile: configFilePath
configFile: configFilePath
}
},
{
text: "```js\n\n" +
"var a = 1;\n\n" +
"```",
"var a = 1;\n\n" +
"```",
options: {
configFile: configFilePath
configFile: configFilePath
}
},
{
text: "```js\n\n" +
"+++1+++\n" +
"```",
"+++1+++\n" +
"```",
options: {
configFile: configFilePath,
ignoreParsingErrors: true
configFile: configFilePath,
ignoreParsingErrors: true
}
},
],
invalid: [
{
text: "```js\n" +
"+++1+++\n" +
"```",
"+++1+++\n" +
"```",
errors: [
{
message: "Parsing error: Assigning to rvalue",
Expand All @@ -59,11 +60,11 @@ tester.run("textlint-rule-eslint", rule, {
},
{
text: "```js\n" +
WrongCode1 + "\n" +
"```",
WrongCode1 + "\n" +
"```",
output: "```js\n" +
WrongCode1 + ";\n" +
"```",
WrongCode1 + ";\n" +
"```",
errors: [
{
message: "semi: Missing semicolon.",
Expand All @@ -75,22 +76,47 @@ tester.run("textlint-rule-eslint", rule, {
configFile: configFilePath
}
},
{
text: "```javascript\n" +
"var a = 1\n" +
"var b = 2\n" +
"```",
output: "```javascript\n" +
"var a = 1;\n" +
"var b = 2;\n" +
"```",
errors: [
{
message: "semi: Missing semicolon.",
line: 2,
column: 10
},
{
message: "semi: Missing semicolon.",
line: 3,
column: 10
}
],
options: {
configFile: configFilePath
}
},
// multiple
{
text: "```js\n" +
WrongCode1 + "\n" +
"```\n" +
"This is text.\n" +
"```js\n" +
WrongCode2 + "\n" +
"```",
WrongCode1 + "\n" +
"```\n" +
"This is text.\n" +
"```js\n" +
WrongCode2 + "\n" +
"```",
output: "```js\n" +
WrongCode1 + ";\n" +
"```\n" +
"This is text.\n" +
"```js\n" +
WrongCode2 + ";\n" +
"```",
WrongCode1 + ";\n" +
"```\n" +
"This is text.\n" +
"```js\n" +
WrongCode2 + ";\n" +
"```",
errors: [
{
message: "semi: Missing semicolon.",
Expand All @@ -107,4 +133,4 @@ tester.run("textlint-rule-eslint", rule, {
}
}
]
});
});
Loading