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(rule): fix false-positive result #3

Merged
merged 2 commits into from
Dec 24, 2017
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
11 changes: 5 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
"devDependencies": {
"babel-register": "^6.26.0",
"husky": "^0.14.3",
"lint-staged": "^4.3.0",
"prettier": "^1.7.4",
"textlint-scripts": "^1.3.0"
"lint-staged": "^6.0.0",
"prettier": "^1.9.2",
"textlint-scripts": "^1.4.0"
},
"prettier": {
"printWidth": 120,
Expand All @@ -53,8 +53,7 @@
},
"dependencies": {
"en-pos": "^1.0.16",
"sentence-splitter": "^2.2.0",
"textlint-rule-helper": "^2.0.0",
"textlint-util-to-string": "^2.1.1"
"sentence-splitter": "^3.0.0",
"textlint-rule-helper": "^2.0.0"
}
}
109 changes: 62 additions & 47 deletions src/textlint-rule-en-capitalization.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
// MIT © 2017 azu
"use strict";
const { RuleHelper } = require("textlint-rule-helper");
const StringSource = require("textlint-util-to-string");
const { split, Syntax: SentenceSyntax } = require("sentence-splitter");
const { splitAST, Syntax: SentenceSyntax } = require("sentence-splitter");
import { getPosFromSingleWord, isCapitalized, upperFirstCharacter } from "./captalize";

const REPORT_TYPE = {
Heading: "Heading",
Paragraph: "Paragraph",
List: "List"
};
const shouldNotCapitalized = (string, allowWords) => {
// allow words
const shouldAllowed = allowWords.some(allowWord => {
Expand All @@ -25,24 +29,6 @@ const shouldNotCapitalized = (string, allowWords) => {
return false;
};

/**
* get node at index
* @param node
* @param index
* @returns {undefined|*}
*/
const getNodeAtIndex = (node, index) => {
if (!node || !node.children) {
return undefined;
}
for (let i = 0; i < node.children.length; i++) {
const childNode = node.children[i];
if (childNode.range[0] <= index && index <= childNode.range[1]) {
return childNode;
}
}
return undefined;
};
/**
* @param node
* @param Syntax
Expand All @@ -52,49 +38,46 @@ const getNodeAtIndex = (node, index) => {
* @param fixer
* @param {boolean} allowFigures enable figures check
* @param {string[]} allowWords allow lower-case words
* @param {string} reportType REPORT_TYPE
*/
const checkNode = ({ node, Syntax, getSource, report, RuleError, fixer, allowFigures, allowWords }) => {
const source = new StringSource(node);
const sourceText = source.toString();
const sentences = split(sourceText);
sentences.filter(sentence => sentence.type === SentenceSyntax.Sentence).forEach(sentence => {
const originalIndex = source.originalIndexFromIndex(sentence.range[0]);
let targetNode;
if (node.type === Syntax.ListItem) {
targetNode = getNodeAtIndex(node.children[0], node.range[0] + originalIndex);
} else {
targetNode = getNodeAtIndex(node, originalIndex);
}
if (!targetNode) {
const checkNode = ({ node, Syntax, getSource, report, RuleError, fixer, allowFigures, allowWords, reportType }) => {
const DocumentURL = "https://owl.english.purdue.edu/owl/resource/592/01/";
const paragraphNode = splitAST(node);
paragraphNode.children.filter(sentence => sentence.type === SentenceSyntax.Sentence).forEach(sentence => {
const sentenceFirstNode = sentence.children[0];
if (!sentenceFirstNode) {
return;
}
const DocumentURL = "https://owl.english.purdue.edu/owl/resource/592/01/";
// check
if (targetNode.type === Syntax.Str) {
const text = sentence.value;
const firstWord = text.split(" ")[0];
// check first word is String
if (sentenceFirstNode.type === Syntax.Str) {
const text = sentenceFirstNode.value;
const firstWord = text.split(/\s/)[0];
if (isCapitalized(firstWord) || shouldNotCapitalized(firstWord, allowWords)) {
return;
}
const index = originalIndex;
const index = 0;
return report(
node,
sentenceFirstNode,
new RuleError(
`Heading: Follow the standard capitalization rules for American English.
`${reportType}: Follow the standard capitalization rules for American English.
See ${DocumentURL}`,
{
index: index,
fix: fixer.replaceTextRange([index, index + firstWord.length], upperFirstCharacter(firstWord))
}
)
);
} else if (allowFigures && targetNode.type === Syntax.Image && typeof targetNode.alt === "string") {
const text = targetNode.alt;
} else if (
allowFigures &&
sentenceFirstNode.type === Syntax.Image &&
typeof sentenceFirstNode.alt === "string"
) {
const text = sentenceFirstNode.alt;
if (isCapitalized(text) || shouldNotCapitalized(text, allowWords)) {
return;
}
return report(
targetNode,
sentenceFirstNode,
new RuleError(
`Image alt: Follow the standard capitalization rules for American English
See ${DocumentURL}`
Expand Down Expand Up @@ -127,7 +110,17 @@ const report = (context, options = {}) => {
if (!allowHeading) {
return;
}
checkNode({ node, Syntax, getSource, report, RuleError, fixer, allowFigures, allowWords });
checkNode({
node,
Syntax,
getSource,
report,
RuleError,
fixer,
allowFigures,
allowWords,
reportType: REPORT_TYPE.Heading
});
},
[Syntax.Paragraph](node) {
if (helper.isChildNode(node, [Syntax.Link, Syntax.Image, Syntax.BlockQuote, Syntax.Emphasis])) {
Expand All @@ -136,13 +129,35 @@ const report = (context, options = {}) => {
if (helper.isChildNode(node, [Syntax.ListItem])) {
return;
}
checkNode({ node, Syntax, getSource, report, RuleError, fixer, allowFigures, allowWords });
checkNode({
node,
Syntax,
getSource,
report,
RuleError,
fixer,
allowFigures,
allowWords,
reportType: REPORT_TYPE.Paragraph
});
},
[Syntax.ListItem](node) {
if (!allowLists) {
return;
}
checkNode({ node, Syntax, getSource, report, RuleError, fixer, allowFigures, allowWords });
node.children.forEach(paragraph => {
checkNode({
node: paragraph,
Syntax,
getSource,
report,
RuleError,
fixer,
allowFigures,
allowWords,
reportType: REPORT_TYPE.List
});
});
}
};
};
Expand Down
2 changes: 1 addition & 1 deletion test/mocha.opts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
--require babel-register
--require textlint-scripts/register
24 changes: 21 additions & 3 deletions test/textlint-rule-en-capitalization-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ tester.run("capitalization", rule, {
valid: [
"In text, follow the standard capitalization rules for American English. Additionally:",
"First, sentence should be capital. Second, sentence should be capital.",
"`Code`, this is ok.",
"This is **good**. But that it not good.",
"# Capitalization in titles and headings",
"## Capitalization and colons\n" +
"Use a lowercase letter to begin the first word of the text immediately following a colon, unless the text is one of the following:",
Expand All @@ -28,7 +30,13 @@ tester.run("capitalization", rule, {
options: {
allowWords: ["textlint"]
}
}
},
// https://github.com/textlint-rule/textlint-rule-en-capitalization/issues/2
`# Anatomy of a Package

A minimal npm package should contain metadata in a _package.json_ file and an associated source file (usually _index.js_). In practice, packages contain more than that and you will have at least a license file and the source in various formats.`,
// need space after .
"This is pass.it's style is bad..."
],
invalid: [
{
Expand All @@ -38,7 +46,7 @@ tester.run("capitalization", rule, {
{
index: 0,
message:
"Heading: Follow the standard capitalization rules for American English.\n" +
"Paragraph: Follow the standard capitalization rules for American English.\n" +
"See https://owl.english.purdue.edu/owl/resource/592/01/"
}
]
Expand Down Expand Up @@ -81,11 +89,21 @@ tester.run("capitalization", rule, {
`,
errors: [{}, {}, {}, {}, {}]
},
{
text: "This is **good**. but that it not good.",
errors: [
{
index: 18
}
]
},
{
text: "![image](http://exmaple.com) is not capital.",
errors: [
{
index: 0
index: 0,
message: `Image alt: Follow the standard capitalization rules for American English
See https://owl.english.purdue.edu/owl/resource/592/01/`
}
]
}
Expand Down
Loading