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
2 changes: 2 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
npx --no-install lint-staged
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,19 @@
"build": "textlint-scripts build",
"prepublish": "npm run --if-present build",
"test": "textlint-scripts test",
"prettier": "prettier --write \"**/*.{js,jsx,ts,tsx,css}\"",
"watch": "textlint-scripts build --watch"
"watch": "textlint-scripts build --watch",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,css}\"",
"prepare": "git config --local core.hooksPath .githooks"
},
"prettier": {
"printWidth": 120,
"singleQuote": false,
"tabWidth": 4
"printWidth": 120,
"tabWidth": 4,
"trailingComma": "none"
},
"devDependencies": {
"husky": "^1.1.1",
"lint-staged": "^7.3.0",
"prettier": "^1.8.1",
"prettier": "^3.1.0",
"textlint-scripts": "^12.0.1",
"textlint-tester": "12.0.0"
},
Expand All @@ -54,8 +55,7 @@
},
"lint-staged": {
"*.{js,jsx,ts,tsx,css}": [
"prettier --write",
"git add"
"prettier --write"
]
},
"dependencies": {
Expand Down
16 changes: 8 additions & 8 deletions src/parser/PairMaker.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const PAIR_MARKS = [
// create entries
// [start.key, mark]
// [end.key, mark]
const PAIR_MARKS_ENTRIES = PAIR_MARKS.map(mark => {
const PAIR_MARKS_ENTRIES = PAIR_MARKS.map((mark) => {
return [
[mark.start, mark],
[mark.end, mark]
Expand All @@ -86,34 +86,34 @@ const PAIR_MARKS_ENTRIES = PAIR_MARKS.map(mark => {
const PAIR_MARKS_KEY_Map = new Map(PAIR_MARKS_ENTRIES);
const matchPair = (string) => {
return PAIR_MARKS_KEY_Map.get(string);
}
};
// For readme
// console.log(PAIR_MARKS.map(pair => `- ${pair.key}: \`${pair.start}\` and \`${pair.end}\``).join("\n"));
export class PairMaker {
/**
* @param {import("./SourceCode").SourceCode} sourceCode
* @returns
* @param {import("./SourceCode").SourceCode} sourceCode
* @returns
*/
mark(sourceCode) {
const string = sourceCode.read();
if (!string) {
return;
}

const matchedPair = matchPair(string)
if (!matchedPair){
const matchedPair = matchPair(string);
if (!matchedPair) {
return;
}
// support nested pair
// {"{test}"}
if (sourceCode.isInContext(matchedPair)) {
// check that string is end mark?
const pair = PAIR_MARKS.find(pair => pair.end === string);
const pair = PAIR_MARKS.find((pair) => pair.end === string);
if (pair) {
sourceCode.leaveContext(pair);
}
} else {
const pair = PAIR_MARKS.find(pair => pair.start === string);
const pair = PAIR_MARKS.find((pair) => pair.start === string);
if (pair) {
sourceCode.enterContext(pair);
}
Expand Down
4 changes: 2 additions & 2 deletions src/parser/SourceCode.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class SourceCode {
}

leaveContext(pairMark) {
const index = this.contextLocations.findIndex(context => {
const index = this.contextLocations.findIndex((context) => {
return context.pairMark.key === pairMark.key;
});
if (index !== -1) {
Expand All @@ -29,7 +29,7 @@ export class SourceCode {
if (!pairMark) {
return this.contextLocations.length > 0;
}
return this.contextLocations.some(contextLocation => contextLocation.pairMark.key === pairMark.key);
return this.contextLocations.some((contextLocation) => contextLocation.pairMark.key === pairMark.key);
}

/**
Expand Down
48 changes: 28 additions & 20 deletions src/textlint-rule-no-unmatched-pair.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { PairMaker } from "./parser/PairMaker.js";
import { SourceCode } from "./parser/SourceCode.js";
import { IgnoreNodeManager } from "textlint-rule-helper";

const report = context => {
const report = (context) => {
const { Syntax, report, RuleError } = context;
const ignoreNodeManager = new IgnoreNodeManager();
return {
Expand All @@ -19,29 +19,37 @@ const report = context => {
Syntax.BlockQuote,
Syntax.Comment
]);
sentences.children.filter(node => node.type === SentenceSplitterSyntax.Sentence).forEach(sentence => {
const source = new SourceCode(sentence.raw);
const pairMaker = new PairMaker();
const sentenceIndex = sentence.range[0];
while (source.canRead) {
// If the character is in ignored range, skip it
const characterIndex = sentenceIndex + source.index;
// console.log(characterIndex, source.text[source.index], ignoreNodeManager.isIgnoredIndex(characterIndex));
if (!ignoreNodeManager.isIgnoredIndex(characterIndex)) {
pairMaker.mark(source);
sentences.children
.filter((node) => node.type === SentenceSplitterSyntax.Sentence)
.forEach((sentence) => {
const source = new SourceCode(sentence.raw);
const pairMaker = new PairMaker();
const sentenceIndex = sentence.range[0];
while (source.canRead) {
// If the character is in ignored range, skip it
const characterIndex = sentenceIndex + source.index;
// console.log(characterIndex, source.text[source.index], ignoreNodeManager.isIgnoredIndex(characterIndex));
if (!ignoreNodeManager.isIgnoredIndex(characterIndex)) {
pairMaker.mark(source);
}
source.peek();
}
source.peek();
}
// Report Error for each existing context keys
source.contextLocations.forEach((contextLocation) => {
report(node, new RuleError(`Not found pair character for ${contextLocation.pairMark.start}.
// Report Error for each existing context keys
source.contextLocations.forEach((contextLocation) => {
report(
node,
new RuleError(
`Not found pair character for ${contextLocation.pairMark.start}.

You should close this sentence with ${contextLocation.pairMark.end}.
This pair mark is called ${contextLocation.pairMark.key}.`, {
index: (sentenceIndex - node.range[0]) + contextLocation.index
}));
This pair mark is called ${contextLocation.pairMark.key}.`,
{
index: sentenceIndex - node.range[0] + contextLocation.index
}
)
);
});
});
});
}
};
};
Expand Down
18 changes: 11 additions & 7 deletions test/textlint-rule-no-unmatched-pair-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ tester.run("textlint-rule-no-unmatched-pair", rule, {
'test {"{ABC`{"{ABC}"}`}"} ok.',
"これは(秘密)です。",
`John said "Hello World!".`,
"`(` is ok.", "文字列リテラルには3種類ありますが、まずは`\"`(ダブルクオート)と`'`(シングルクオート)について見ていきます。",
"`(` is ok.",
"文字列リテラルには3種類ありますが、まずは`\"`(ダブルクオート)と`'`(シングルクオート)について見ていきます。",
`a is b.

\`"\`(ダブルクオート)と\`'\`(シングルクオート)に意味的な違いはありません。
Expand All @@ -21,7 +22,8 @@ tester.run("textlint-rule-no-unmatched-pair", rule, {

また操作と表示が1対1で更新される場合、1つの操作に対して複数の箇所の表示が更新されることもあります。
今回のTodoアプリでもTodoリスト(\`#js-todo-list\`)とTodoアイテム数(\`#js-todo-count\`)の2箇所を更新する必要があることからも分かります。
`, `\`Object.assign\`メソッドは、\`target\`オブジェクトに対して、1つ以上の\`sources\`オブジェクトを指定します。
`,
`\`Object.assign\`メソッドは、\`target\`オブジェクトに対して、1つ以上の\`sources\`オブジェクトを指定します。
\`sources\`オブジェクト自身がもつ列挙可能なプロパティを第一引数の\`target\`オブジェクトに対してコピーします。
\`Object.assign\`メソッドの返り値は、\`target\`オブジェクトになります。`,
// 箇条書き
Expand Down Expand Up @@ -63,14 +65,16 @@ This pair mark is called double quote.`
]
},
{
text: "`src/App.js`にファイルを作成し、次のような内容のJavaScriptモジュールとします。\n"
+ "モジュールは、基本的には何かしらを外部に公開(`export`)します。",
text:
"`src/App.js`にファイルを作成し、次のような内容のJavaScriptモジュールとします。\n" +
"モジュールは、基本的には何かしらを外部に公開(`export`)します。",
errors: [
{
index: 74
}
]
}, {
},
{
text: `このように\`count\`変数が自動解放されずに保持できているのは「(\`increment\`)関数が外側のスコープにある(\`count\`)変数への参照を保持できる」ためです。このような性質のことをクロージャー(関数閉包)と呼びます。クロージャーは静的スコープと変数は参照され続けていればデータは保持されるという2つの性質によって成り立っています。`,
errors: [
{
Expand All @@ -79,7 +83,8 @@ This pair mark is called double quote.`
index: 104
}
]
},{
},
{
text: `DUMMY DUUMY.


Expand All @@ -93,4 +98,3 @@ This pair mark is called double quote.`
}
]
});

Loading