diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..170443f --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,20 @@ +name: test +on: [push, pull_request] +jobs: + test: + name: "Test on Node.js ${{ matrix.node-version }}" + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [12, 14] + steps: + - name: checkout + uses: actions/checkout@v2 + - name: setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + - name: Install + run: yarn install + - name: Test + run: yarn test diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 87576c5..0000000 --- a/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -sudo: false -language: node_js -node_js: stable diff --git a/README.md b/README.md index 9094858..d934f1d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -# textlint-rule-no-double-negative-ja [![Build Status](https://travis-ci.org/textlint-ja/textlint-rule-no-double-negative-ja.svg?branch=master)](https://travis-ci.org/textlint-ja/textlint-rule-no-double-negative-ja) +# textlint-rule-no-double-negative-ja [![Actions Status: test](https://github.com/textlint-ja/textlint-rule-no-double-negative-ja/workflows/test/badge.svg)](https://github.com/textlint-ja/textlint-rule-no-double-negative-ja/actions?query=workflow%3A"test") -[二重否定](https://ja.wikipedia.org/wiki/%E4%BA%8C%E9%87%8D%E5%90%A6%E5%AE%9A_(%E8%A8%80%E8%AA%9E%E5%AD%A6) "二重否定")を検出する[textlint](https://github.com/textlint/textlint "textlint")ルールです。 +[二重否定](https://ja.wikipedia.org/wiki/%E4%BA%8C%E9%87%8D%E5%90%A6%E5%AE%9A_(%E8%A8%80%E8%AA%9E%E5%AD%A6) "二重否定") +を検出する[textlint](https://github.com/textlint/textlint "textlint")ルールです。 > ✘ それが事件の発端だったといえなくもない。 @@ -12,7 +13,7 @@ などの二重否定を検出することができます。 -二重否定の用法については[<研究論文>二重否定表現「~なくは/ もない」「~ないでも/ はない」「~ないことは/ もない」「~ないものでは/ もない」の使い分けを巡って](http://repository.kulib.kyoto-u.ac.jp/dspace/bitstream/2433/187059/1/Ronko3_043.pdf "Ronko3_043.pdf")を参照してください。 +二重否定の用法については、[<研究論文>二重否定表現「~なくは/もない」「~ないでも/はない」「~ないことは/もない」「~ないものでは/もない」の使い分けを巡って](https://repository.kulib.kyoto-u.ac.jp/dspace/bitstream/2433/187059/1/Ronko3_043.pdf)を参照してください。 ## Installation @@ -24,23 +25,26 @@ ```js { - "rules": { - "no-double-negative-ja": true + "rules" +: + { + "no-double-negative-ja" + : + true } } ``` ## Tests - + npm test ## 参考文献 -- http://repository.kulib.kyoto-u.ac.jp/dspace/bitastream/2433/187059/1/Ronko3_043.pdf +- [<研究論文>二重否定表現「~なくは/もない」「~ないでも/はない」「~ないことは/もない」「~ないものでは/もない」の使い分けを巡って](https://repository.kulib.kyoto-u.ac.jp/dspace/bitstream/2433/187059/1/Ronko3_043.pdf) - http://www.asahi-net.or.jp/~wd2y-kkb/n.htm#%E4%BA%8C%E9%87%8D%E5%90%A6%E5%AE%9A - https://github.com/redpen-cc/redpen/blob/master/redpen-core/src/main/resources/default-resources/double-negative/double-negative-expression-ja.dat - ## Contributing 1. Fork it! @@ -51,4 +55,4 @@ ## License -MIT \ No newline at end of file +MIT diff --git a/package.json b/package.json index 795200a..45464de 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,6 @@ "textlint-scripts": "^3.0.0" }, "dependencies": { - "kuromojin": "^2.0.0" + "kuromojin": "^3.0.0" } } diff --git a/src/matchTokenStream.js b/src/matchTokenStream.js index e972ff9..0d7c7d4 100644 --- a/src/matchTokenStream.js +++ b/src/matchTokenStream.js @@ -1,6 +1,19 @@ // LICENSE : MIT "use strict"; + +/** + * expectShape + * [expectShape | expectShape] + * にどれかにマッチするならtrueを返す + * @param {*} token + * @param {*|*[]} expectShape + * orでマッチしたい場合は配列を渡す + * @returns {boolean} + */ function matchToken(token, expectShape) { + if (Array.isArray(expectShape)) { + return expectShape.some(singleExpectShape => matchToken(token, singleExpectShape)); + } return Object.keys(expectShape).every(key => { const actualValue = token[key]; // 値は複数の場合もある @@ -10,6 +23,7 @@ function matchToken(token, expectShape) { }); }) } + export default function expectTokenStream(tokenStream) { let currentTokenPosition = 0; const tokenCount = tokenStream.length; @@ -29,4 +43,4 @@ export default function expectTokenStream(tokenStream) { } return false; } -} \ No newline at end of file +} diff --git a/src/rules/naikotoha-nai.js b/src/rules/naikotoha-nai.js index b39c2d6..d5ca93a 100644 --- a/src/rules/naikotoha-nai.js +++ b/src/rules/naikotoha-nai.js @@ -5,8 +5,9 @@ ~ない(否定助動詞 / 否定形容詞の連体形) + 形式名詞「こと」+ とりたて助詞「は / も」+ 形容詞「ない」 */ import matchTokenStream from "./../matchTokenStream"; + export default function (context) { - const {RuleError} = context; + const { RuleError } = context; const matchPatternないことはない = matchTokenStream([ { "basic_form": ["ない", "無い"] @@ -36,10 +37,18 @@ export default function (context) { "surface_form": "も", "pos": "助詞" }, - { - "basic_form": ["ない", "無い"], - "pos": "形容詞" - } + [ + // ないこともないでしょう。 + { + "basic_form": ["ない", "無い"], + "conjugated_type": ["特殊・ナイ"] + }, + // ないこともない。 + { + "basic_form": ["ない", "無い"], + "pos": "形容詞" + } + ] ]); return (token) => { if (matchPatternないことはない(token)) { @@ -53,4 +62,4 @@ export default function (context) { }); } }; -} \ No newline at end of file +} diff --git a/test/no-doubled-negative-ja-test.js b/test/no-doubled-negative-ja-test.js index 0b03011..1409ca9 100644 --- a/test/no-doubled-negative-ja-test.js +++ b/test/no-doubled-negative-ja-test.js @@ -135,6 +135,15 @@ tester.run("no-doubled-negative", rule, { } ] }, + { + text: "そういう話なら、ないこともないでしょう。", + errors: [ + { + message: "二重否定: 〜ないこともない", + column: 14 + } + ] + }, // e { text: "ないわけでもないですが", @@ -209,6 +218,16 @@ tester.run("no-doubled-negative", rule, { column: 9 } ] - } + }, + // 3重否定 + { + text: "憂鬱でないこともないこともない。", + errors: [ + { + message: "二重否定: 〜ないこともない", + column: 9 + } + ] + }, ] -}); \ No newline at end of file +}); diff --git a/yarn.lock b/yarn.lock index a0e0546..df37ade 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2250,21 +2250,22 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -kuromoji@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/kuromoji/-/kuromoji-0.1.1.tgz#4aabf39bcced8b8ad92d007a04a26be6da8477c9" - integrity sha1-Sqvzm8zti4rZLQB6BKJr5tqEd8k= +kuromoji@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/kuromoji/-/kuromoji-0.1.2.tgz#293f0d6706df006112137980588d5daac26d0790" + integrity sha512-V0dUf+C2LpcPEXhoHLMAop/bOht16Dyr+mDiIE39yX3vqau7p80De/koFqpiTcL1zzdZlc3xuHZ8u5gjYRfFaQ== dependencies: async "^2.0.1" doublearray "0.0.2" - zlibjs "^0.2.0" + zlibjs "^0.3.1" -kuromojin@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/kuromojin/-/kuromojin-2.0.0.tgz#23e74a5ed2578432c9703ae75a69ba0a09ccb12d" - integrity sha512-60j/yLkFSc4t4roj8tI8ZNNSiAFnrkgXw8SqXz/9nakfs6mkCvPbrd7S8LDr4YNwEt1IyLys5JQTR9EnYyGHhA== +kuromojin@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/kuromojin/-/kuromojin-3.0.0.tgz#54a1a6643110f49f741c4beb82fef400d1cd498b" + integrity sha512-3h3qnn/NVVhqoKFP4oc7e6apO2B01Atc056oiVlIY7Uoup4rhrnBe28g3y9lK1HTmLDQEejvXB+3I3qxAneF7A== dependencies: - kuromoji "0.1.1" + kuromoji "0.1.2" + lru_map "^0.4.1" leven@^3.1.0: version "3.1.0" @@ -2357,6 +2358,11 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" +lru_map@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.4.1.tgz#f7b4046283c79fb7370c36f8fca6aee4324b0a98" + integrity sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg== + make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -3811,7 +3817,7 @@ yargs@13.3.2, yargs@^13.3.0: y18n "^4.0.0" yargs-parser "^13.1.2" -zlibjs@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/zlibjs/-/zlibjs-0.2.0.tgz#ae20f06243293d85c255563189f9b12f5b3ba1a0" - integrity sha1-riDwYkMpPYXCVVYxifmxL1s7oaA= +zlibjs@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/zlibjs/-/zlibjs-0.3.1.tgz#50197edb28a1c42ca659cc8b4e6a9ddd6d444554" + integrity sha1-UBl+2yihxCymWcyLTmqd3W1ERVQ=