├── .gitignore
├── test
├── doc
│ ├── use-hiragana-and-kanji-properly-v2.md
│ ├── numeral-must-be-hankaku.md
│ ├── alphabet-must-be-one-byte.md
│ ├── dont-use-can-do.md
│ ├── kuten.md
│ ├── dont-use-kosoado.md
│ ├── ka-is-written-in-hiragana.md
│ ├── use-assertive-style.md
│ ├── use-numeral-properly.md
│ ├── symbol.md
│ ├── katakana-must-be-two-byte.md
│ ├── use-literary-style.md
│ └── use-hiragana-and-kanji-properly.md
├── redpen-conf.xml
└── script
│ ├── kuten.js
│ ├── symbol.js
│ ├── dont-use-can-do.js
│ ├── use-assertive-style.js
│ ├── dont-use-kosoado.js
│ ├── use-numeral-properly.js
│ ├── use-literary-style.js
│ ├── numeral-must-be-hankaku.js
│ ├── alphabet-must-be-one-byte.js
│ ├── ka-is-written-in-hiragana.js
│ ├── katakana-must-be-two-byte.js
│ ├── use-hiragana-and-kanji-properly.js
│ └── use-hiragana-and-kanji-properly-v2.js
├── script
└── build_dictionary
│ ├── package.json
│ └── build-dictionar.js
├── katakana-must-be-two-byte.js
├── alphabet-must-be-one-byte.js
├── numeral-must-be-hankaku.js
├── package.json
├── .codeclimate.yml
├── circle.yml
├── LICENSE
├── ka-is-written-in-hiragana.js
├── symbol.js
├── termsValidator.js
├── custom-pattern.js
├── use-hiragana-and-kanji-properly-v2.js
├── README.md
├── dont-use-can-do.js
├── use-assertive-style.js
├── use-numeral-properly.js
├── use-literary-style.js
├── dont-use-kosoado.js
├── use-joyo-Kanji.js
└── use-hiragana-and-kanji-properly.js
/.gitignore:
--------------------------------------------------------------------------------
1 | script/*/node_modules
2 |
--------------------------------------------------------------------------------
/test/doc/use-hiragana-and-kanji-properly-v2.md:
--------------------------------------------------------------------------------
1 | 学習する上で邪魔です。
2 |
--------------------------------------------------------------------------------
/test/doc/numeral-must-be-hankaku.md:
--------------------------------------------------------------------------------
1 | お皿が1枚あります。
2 |
3 | 動物が1匹います
4 |
--------------------------------------------------------------------------------
/test/doc/alphabet-must-be-one-byte.md:
--------------------------------------------------------------------------------
1 | ABCは全角です。アルファベットは半角を使わなければなりません。
2 |
--------------------------------------------------------------------------------
/test/doc/dont-use-can-do.md:
--------------------------------------------------------------------------------
1 | 勉強することができる
2 |
3 | 勉強することが出来る
4 |
5 | 勉強する事ができた
6 |
7 | 勉強する事が出来る
8 |
--------------------------------------------------------------------------------
/test/redpen-conf.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/test/doc/kuten.md:
--------------------------------------------------------------------------------
1 | # テスト文章。
2 |
3 | ## テスト文章その1。
4 |
5 | - 箇条書きの最後には句点をつけます
6 | - 箇条書きの最後が体言止めの場合は、句点をつけないこと。
7 | - ごはん。
8 | - 美しさ。
9 |
10 | 本文の最後には句点をつけてください
11 |
12 | 丸かっこ(丸かっことは丸かっこのことです。)には句点をつけません。
13 |
14 | 鍵かっこ(鍵カッコとは鍵カッコのことです。)には句点をつけません。
15 |
--------------------------------------------------------------------------------
/test/doc/dont-use-kosoado.md:
--------------------------------------------------------------------------------
1 | これはあのご飯です。
2 |
3 | それはご飯です。
4 |
5 | あれはどのご飯です。
6 |
7 | どれがご飯ですか。
8 |
9 | このご飯は何味ですか。
10 |
11 | そのご飯は何味ですか。
12 |
13 | あのご飯は何味ですか。
14 |
15 | どのご飯を食べますか。
16 |
17 | ここは東京都ですか。
18 |
19 | そこは地雷原です。
20 |
21 | あそこは地雷原です。
22 |
23 | 地雷原はどこですか。
24 |
25 | 地雷原はそちらです。
26 |
27 | 地雷原はあちらです。
28 |
29 | どちらに地雷原がありますか。
30 |
--------------------------------------------------------------------------------
/test/doc/ka-is-written-in-hiragana.md:
--------------------------------------------------------------------------------
1 | 1ヵ月
2 |
3 | 1カ月
4 |
5 | 1ヶ月
6 |
7 | 1ケ月
8 |
9 | 1箇月
10 |
11 | 1個月
12 |
13 | 1ヵ所
14 |
15 | 1カ所
16 |
17 | 1ヶ所
18 |
19 | 1ケ所
20 |
21 | 1箇所
22 |
23 | 1個所
24 |
25 | 1ヵ国
26 |
27 | 1カ国
28 |
29 | 1ヶ国
30 |
31 | 1ケ国
32 |
33 | 1箇国
34 |
35 | 1個国
36 |
37 | 1ヵ年
38 |
39 | 1カ年
40 |
41 | 1ヶ年
42 |
43 | 1ケ年
44 |
45 | 1箇年
46 |
47 | 1個年
48 |
--------------------------------------------------------------------------------
/script/build_dictionary/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "build_dictionary",
3 | "version": "0.0.1",
4 | "description": "",
5 | "main": "build-dictionar.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "kongou-ae",
10 | "license": "MIT",
11 | "dependencies": {
12 | "argv": "0.0.2",
13 | "request": "^2.74.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/test/doc/use-assertive-style.md:
--------------------------------------------------------------------------------
1 | 元気だと感じた。
2 |
3 | 元気だと感じる。
4 |
5 | 無駄な表現だと考えられる。
6 |
7 | 無駄な表現だと考えられます。
8 |
9 | 高温であることが分かる。
10 |
11 | 高温であることがわかる。
12 |
13 | ご飯を食べたいと思います。
14 |
15 | ご飯を食べたいと思う。
16 |
17 | ご飯を食べたいと思われる。
18 |
19 | あれはご飯かもしれない。
20 |
21 | ご飯を食べるかもしれない
22 |
23 | ご飯を食べるのではないだろうか。
24 |
25 | まず相手の気持ちを知る必要があるでしょう。
26 |
27 | 相手の気持ちを知る必要があるでしょうか。
28 |
29 | わかりやすい
30 |
31 | わかりにくい
32 |
33 | ですが
34 |
35 | 今回は、挑戦しない人ではなく、挑戦したいことがあるのに挑戦できない人です。
36 |
--------------------------------------------------------------------------------
/test/doc/use-numeral-properly.md:
--------------------------------------------------------------------------------
1 | # 検知すべき単語
2 |
3 | 三つのボタン
4 |
5 | 第三回大会
6 |
7 | 四か月
8 |
9 | 一番目
10 |
11 | 二進法
12 |
13 | 三次元
14 |
15 | 5大陸
16 |
17 | 1次関数
18 |
19 | 1時的
20 |
21 | # 検知してはいけない単語
22 |
23 | 一言一句
24 |
25 | 1億2805万人
26 |
27 | 3つのボタン
28 |
29 | 第3回大会
30 |
31 | 4か月
32 |
33 | 1番目、2番目
34 |
35 | 2進法
36 |
37 | 3次元
38 |
39 | 四捨五入
40 |
41 | 一汁三菜
42 |
43 | 一期一会
44 |
45 | 世界一
46 |
47 | 一時的
48 |
49 | 一部分
50 |
51 | 第三者
52 |
53 | 一種の
54 |
55 | 一部の
56 |
57 | 一番に
58 |
59 | 数百倍
60 |
61 | 二次関数
62 |
63 | 四捨五入
64 |
65 | 四角い
66 |
67 | 五大陸
68 |
--------------------------------------------------------------------------------
/katakana-must-be-two-byte.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 参考
3 | // https://www.jtf.jp/jp/style_guide/pdf/jtf_style_guide.pdf
4 | // 2.1.5. カタカナ
5 | // カタカナは「全角」で表記します。半角カタカナは特殊な用途を除いて、原則として使いません。
6 | var terms = [
7 | {
8 | 'expected':'[ァ-ンヲ]',
9 | 'pattern':['[ァ-ンヲ]']
10 | }
11 | ];
12 |
13 | var regex = new RegExp( terms[0]['pattern'], 'g');
14 | // 形態素解析するかどうか
15 | if ( sentence.content.match(regex) ) {
16 | addError('半角のカタカナが含まれています。全角に修正してください', sentence);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/alphabet-must-be-one-byte.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 参考
3 | // https://www.jtf.jp/jp/style_guide/pdf/jtf_style_guide.pdf
4 | // 2.1.9. アルファベット
5 | // アルファベットは「半角」で表記します。用途によっては全角を許容します。ただし、表記をできるだけ統一するため、特別な理由がない限り半角での表記を原則とします。
6 |
7 | var terms = [
8 | {
9 | 'expected':'[a-zA-Z]',
10 | 'pattern':['[a-zA-Z]']
11 | }
12 | ];
13 |
14 | var regex = new RegExp( terms[0]['pattern'], 'g');
15 | // 形態素解析するかどうか
16 | if ( sentence.content.match(regex) ) {
17 | addError('全角のアルファベットが含まれています。半角に修正してください', sentence);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/numeral-must-be-hankaku.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 参考
3 | // https://www.jtf.jp/jp/style_guide/pdf/jtf_style_guide.pdf
4 | // 2.1.8. 算用数字の実装
5 | // 算用数字は「半角」で表記します。用途によっては全角を許容します。ただし、表記をできるだけ統一するため、特別な理由がない限り半角での表記を原則とします。
6 |
7 | var terms = [
8 | {
9 | 'expected':'[0123456789]',
10 | 'pattern':['[0123456789]']
11 | }
12 | ];
13 |
14 | var regex = new RegExp( terms[0]['pattern'], 'g');
15 | // 形態素解析するかどうか
16 | if ( sentence.content.match(regex) ) {
17 | addError('全角の算用数字が含まれています。半角に修正してください', sentence);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/test/doc/symbol.md:
--------------------------------------------------------------------------------
1 | かっこ(特にまるかっこ)は全角を使います。
2 |
3 | かっこ(特にまるかっこ)は全角を使います。
4 |
5 | なんですと!?
6 |
7 | なんですと!?
8 |
9 | 小・中学校
10 |
11 | パーソナル・コンピュータ
12 |
13 | 3-5歳の子供です
14 |
15 | -
16 |
17 | 日時:9月10日
18 |
19 | 日時;9月10日
20 |
21 | いわゆる"スマート"な都市
22 |
23 | いわゆる’スマート’な都市
24 |
25 | いわゆる‘スマート’な都市
26 |
27 | 明日{つまり7月20日}は誕生日です。
28 |
29 | 明日<つまり7月20日>は誕生日です。
30 |
31 | 連絡先はy.matsu-moto.ae@gmail.comとy.matsu-moto.ae2@gmail.comです。
32 |
33 | y.matsu-moto.ae@gmail.comとy.matsu-moto.ae2@gmail.com
34 |
35 | 3-5歳の担当者のメールアドレスはy.matsu-moto.ae@gmail.comとy.matsu-moto.ae2@gmail.comです。
36 |
37 | 現在の時刻は17:30です。
38 |
39 | 03-3227-5744
40 |
41 | 東京都中央区1-1-1
42 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "redpen-validator-easy-to-read-japanese-document",
3 | "version": "0.0.5",
4 | "description": "redpen custom validator for writing a easy-to-read japanese document",
5 | "main": "alphabet-must-be-one-byte.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\""
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/kongou-ae/redpen-validator.git"
15 | },
16 | "keywords": [
17 | "redpen"
18 | ],
19 | "author": "kongou-ae",
20 | "license": "MIT",
21 | "bugs": {
22 | "url": "https://github.com/kongou-ae/redpen-validator/issues"
23 | },
24 | "homepage": "https://github.com/kongou-ae/redpen-validator#readme"
25 | }
26 |
--------------------------------------------------------------------------------
/test/script/kuten.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 9
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('kuten.js'),
6 | w = fs.createWriteStream('test/kuten.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/kuten.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/kuten.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/script/symbol.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 16;
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('symbol.js'),
6 | w = fs.createWriteStream('test/symbol.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/symbol.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/symbol.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/.codeclimate.yml:
--------------------------------------------------------------------------------
1 | engines:
2 | brakeman:
3 | enabled: false
4 | bundler-audit:
5 | enabled: false
6 | csslint:
7 | enabled: false
8 | coffeelint:
9 | enabled: false
10 | duplication:
11 | enabled: false
12 | config:
13 | languages:
14 | - ruby
15 | - javascript
16 | - python
17 | - php
18 | eslint:
19 | enabled: true
20 | fixme:
21 | enabled: false
22 | rubocop:
23 | enabled: false
24 | ratings:
25 | paths:
26 | - Gemfile.lock
27 | - "**.erb"
28 | - "**.haml"
29 | - "**.rb"
30 | - "**.rhtml"
31 | - "**.slim"
32 | - "**.css"
33 | - "**.coffee"
34 | - "**.inc"
35 | - "**.js"
36 | - "**.jsx"
37 | - "**.module"
38 | - "**.php"
39 | - "**.py"
40 | exclude_paths:
41 | - config/**/*
42 | - db/**/*
43 | - spec/**/*
44 | - vendor/**/*
--------------------------------------------------------------------------------
/test/doc/katakana-must-be-two-byte.md:
--------------------------------------------------------------------------------
1 | ア
2 |
3 | イ
4 |
5 | ウ
6 |
7 | エ
8 |
9 | オ
10 |
11 | カ
12 |
13 | キ
14 |
15 | ク
16 |
17 | ケ
18 |
19 | コ
20 |
21 | サ
22 |
23 | シ
24 |
25 | ス
26 |
27 | セ
28 |
29 | ソ
30 |
31 | タ
32 |
33 | チ
34 |
35 | ツ
36 |
37 | テ
38 |
39 | ト
40 |
41 | ナ
42 |
43 | ニ
44 |
45 | ヌ
46 |
47 | ネ
48 |
49 | ノ
50 |
51 | ハ
52 |
53 | ヒ
54 |
55 | フ
56 |
57 | ヘ
58 |
59 | ホ
60 |
61 | マ
62 |
63 | ミ
64 |
65 | ム
66 |
67 | メ
68 |
69 | モ
70 |
71 | ヤ
72 |
73 | ユ
74 |
75 | ヨ
76 |
77 | ラ
78 |
79 | リ
80 |
81 | ル
82 |
83 | レ
84 |
85 | ロ
86 |
87 | ワ
88 |
89 | ヲ
90 |
91 | ン
92 |
93 | ァ
94 |
95 | ィ
96 |
97 | ゥ
98 |
99 | ェ
100 |
101 | ォ
102 |
103 | ャ
104 |
105 | ュ
106 |
107 | ョ
108 |
109 | ッ
110 |
--------------------------------------------------------------------------------
/test/doc/use-literary-style.md:
--------------------------------------------------------------------------------
1 | あまりにもひどい話だ。
2 |
3 | いっぺんにやってしまおう
4 |
5 | ご飯を食べました。あと、ジュースを飲みました。
6 |
7 | 勉強をやる
8 |
9 | コーチをしてやった
10 |
11 | 明日出かけるけど一緒に来る?
12 |
13 | いい映画だった
14 |
15 | 明日だったら会えますよ
16 |
17 | 狐みたいな狸
18 |
19 | ごはんとかパンとかを食べます
20 |
21 | ごはんじゃなくてパンを食べます
22 |
23 | すごくきれいです
24 |
25 | 超すごい花火でした
26 |
27 | まじですごい花火でした
28 |
29 | パンチをまともにくらってしまった
30 |
31 | パンチをもろにくらった
32 |
33 | 試験は簡単でした。
34 |
35 | 試験は楽でした
36 |
37 | ご飯を食べるのは面倒です。
38 |
39 | このテストは難儀です。
40 |
41 | 厄介な敵にあってしまった。
42 |
43 | 敵を発見すると酸を出して攻撃する性質を持つ。
44 |
45 | わたしは勉強しないといけない。
46 |
47 | わたしはご飯をたべないといけない
48 |
49 | ご飯を食べました。だからご飯を食べましょう。
50 |
51 | ご飯を食べました。それでおなかがいっぱいです。
52 |
53 | すいません。ご飯をとってください。
54 |
55 | ちなみに、明日はご飯を食べますか。
56 |
57 | 雨が降ってます
58 |
59 | 雨が降ってません
60 |
61 | あの白いやつをとってください。
62 |
63 | 赤字になってしまいます。
64 |
--------------------------------------------------------------------------------
/test/script/dont-use-can-do.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 4
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('dont-use-can-do.js'),
6 | w = fs.createWriteStream('test/dont-use-can-do.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/dont-use-can-do.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/dont-use-can-do.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/script/use-assertive-style.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 14
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('use-assertive-style.js'),
6 | w = fs.createWriteStream('test/use-assertive-style.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/use-assertive-style.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/use-assertive-style.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/script/dont-use-kosoado.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 2;
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('dont-use-kosoado.js'),
6 | w = fs.createWriteStream('test/dont-use-kosoado.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/dont-use-kosoado.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/dont-use-kosoado.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/script/use-numeral-properly.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 9
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('use-numeral-properly.js'),
6 | w = fs.createWriteStream('test/use-numeral-properly.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/use-numeral-properly.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/use-numeral-properly.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/script/use-literary-style.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 40
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('use-literary-style.js'),
6 | w = fs.createWriteStream('test/use-literary-style.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/use-literary-style.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/use-literary-style.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/script/numeral-must-be-hankaku.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 2;
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('numeral-must-be-hankaku.js'),
6 | w = fs.createWriteStream('test/numeral-must-be-hankaku.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/numeral-must-be-hankaku.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/numeral-must-be-hankaku.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/script/alphabet-must-be-one-byte.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 1;
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('alphabet-must-be-one-byte.js'),
6 | w = fs.createWriteStream('test/alphabet-must-be-one-byte.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/alphabet-must-be-one-byte.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/alphabet-must-be-one-byte.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/script/ka-is-written-in-hiragana.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 24;
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('ka-is-written-in-hiragana.js'),
6 | w = fs.createWriteStream('test/ka-is-written-in-hiragana.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/ka-is-written-in-hiragana.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/ka-is-written-in-hiragana.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/script/katakana-must-be-two-byte.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 55
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('katakana-must-be-two-byte.js'),
6 | w = fs.createWriteStream('test/katakana-must-be-two-byte.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/katakana-must-be-two-byte.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/katakana-must-be-two-byte.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/script/use-hiragana-and-kanji-properly.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 82
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('use-hiragana-and-kanji-properly.js'),
6 | w = fs.createWriteStream('test/use-hiragana-and-kanji-properly.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/use-hiragana-and-kanji-properly.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/use-hiragana-and-kanji-properly.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/script/use-hiragana-and-kanji-properly-v2.js:
--------------------------------------------------------------------------------
1 | var expectedResult = 1
2 | var exec = require('child_process').exec;
3 | var fs = require('fs');
4 |
5 | var r = fs.createReadStream('use-hiragana-and-kanji-properly-v2.js'),
6 | w = fs.createWriteStream('test/use-hiragana-and-kanji-properly-v2.js');
7 |
8 | r.pipe(w);
9 | w.on('close', function(){
10 | exec('redpen -c test/redpen-conf.xml test/doc/use-hiragana-and-kanji-properly-v2.md -r json -l 100', function(err, stdout, stderr){
11 | if (err) throw err;
12 | fs.unlink('test/use-hiragana-and-kanji-properly-v2.js',function(){
13 | var result = JSON.parse(stdout)
14 | if (result[0].errors.length !== expectedResult){
15 | throw new Error(result[0].errors.length + " error was occured. It is unexpected.")
16 | } else {
17 | console.log(result[0].errors.length + " error was occured. This is expected.")
18 | }
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | machine:
2 | environment:
3 | PATH: /home/ubuntu/redpen-validator/redpen-distribution-1.6.2/bin:$PATH
4 | timezone: Asia/Tokyo
5 | java:
6 | version: oraclejdk8
7 |
8 | dependencies:
9 | pre:
10 | - wget https://github.com/redpen-cc/redpen/releases/download/redpen-1.6.2/redpen-1.6.2.tar.gz
11 | - tar xvf redpen-1.6.2.tar.gz
12 | - rm redpen-1.6.2.tar.gz
13 |
14 | test:
15 | post:
16 | - node test/script/alphabet-must-be-one-byte.js
17 | - node test/script/ka-is-written-in-hiragana.js
18 | - node test/script/katakana-must-be-two-byte.js
19 | - node test/script/use-literary-style.js
20 | - node test/script/symbol.js
21 | - node test/script/use-numeral-properly.js
22 | - node test/script/numeral-must-be-hankaku.js
23 | - node test/script/use-hiragana-and-kanji-properly.js
24 | - node test/script/use-assertive-style.js
25 | - node test/script/dont-use-kosoado.js
26 | - node test/script/use-hiragana-and-kanji-properly-v2.js
27 | - node test/script/dont-use-can-do.js
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 kongou-ae
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/test/doc/use-hiragana-and-kanji-properly.md:
--------------------------------------------------------------------------------
1 | 予め用意しておきます。
2 |
3 | 何れわかる時が来ます。
4 |
5 | 何時頃
6 |
7 | 凡そ五営業日です。
8 |
9 | 却って悪化した。
10 |
11 | 且つ、ご飯を食べなければなりません。
12 |
13 | ご飯かも知れない。
14 |
15 | ご飯を食べて下さい。
16 |
17 | これ程おいしいご飯はありません。
18 |
19 | こどもたち、御確認をお願いします。
20 |
21 | 子供は全品半額。更にポイント5倍。然し在庫なし。暫くお待ちください。即ち在庫切れ。折角なので別の店に行く。度々行ったことのある、あのお店に行く。但し、今日は1人で行く。あの人達と一緒ではなく1人で行く。
22 |
23 | 何処でもご飯を食べることが出来る。
24 |
25 | ご飯ないしはパン。尚、麺は含まない。中々困難なルールである。
26 |
27 | ご飯を食べる。又はパンを食べる。寧ろ麺を食べる。滅多に芋は食べない。最早雑食である。
28 |
29 | ご飯を食べる。もしくはパンを食べる。この結果を以て雑食とする。
30 |
31 | この結果を以って雑食とする。
32 |
33 | ご飯を食べる様にパンを食べる人は変態です。余程のことがない限り、好きにはなりません。いっさいの同情を捨てましょう。かならず裏切られます。同情を注ぐのはおおいに結構。しいて言えば無駄です。ときどきむなしくなりませんか。なにしろ変態です。なんらかの結果を抱えています。なんとも言えない欠陥を抱えています。
34 |
35 | 3個所の個条書きをなおしてください。
36 |
37 | 磨耗する
38 |
39 | 磨滅する
40 |
41 | ごはん及びパンを食べる。影響がおよびます
42 |
43 | 御確認をお願い致します。
44 |
45 | 思いをいたします。従って、ルールにしたがってご飯を食べなけれななりません。
46 |
47 | 利子がつきました。
48 |
49 | 以下の通り、2とおりのパターンがほしいので考えて欲しい。
50 |
51 | 余りに邪魔です。極めて邪魔です。様々な障害がありますが、既に全て排除しています。
52 |
53 | 共に敵を排除しよう。例えば、ご飯です。直ちに倒さなければなりません。到底不可能です。果たして勝利できるのでしょうか。一際目立つ戦いです。他の戦いを見る時間はありません。この他の試合は思いの外退屈です。
54 |
55 | 外ならぬあなたの頼みですが、全く賛成できません。元々分かりませんでした。
56 |
57 | 他ならぬあなたの頼みです。
58 |
59 | 私は判りません。我々は一つ一つが解りません。我が闘争。
60 |
--------------------------------------------------------------------------------
/script/build_dictionary/build-dictionar.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | // RedpenServerのURL
4 | var respenServerURL = 'http://redpen.herokuapp.com/';
5 | // 出力で利用するインデント文字
6 | var indentString = ' ';
7 |
8 | var request = require('request');
9 | var argv = require('argv');
10 |
11 | var cliOptions = {
12 | name: 'document',
13 | short: 'd',
14 | type: 'string',
15 | description: 'document',
16 | example: "'script --document=value' or 'script -d value'"
17 | };
18 |
19 | var form = {};
20 | var args = argv.option(cliOptions).run();
21 | form.document = args.options.document;
22 | form.lang = 'ja';
23 |
24 | var requestOptions = {
25 | url: respenServerURL + 'rest/document/tokenize',
26 | method: 'POST',
27 | headers : {
28 | 'Content-Type':'application/x-www-form-urlencoded'
29 | },
30 | json: true,
31 | form: form
32 | };
33 |
34 | var tokens = [];
35 | var tokenTags = [];
36 | var tmpDictOjb = {};
37 | var dictObj = {};
38 |
39 | request(requestOptions, function (error, response, body) {
40 | if ( error ){
41 | throw new Error( console.log(error));
42 | }
43 |
44 | if ( response.statusCode === 200 ) {
45 | for (var i = 0; i < body.tokens.length; i++){
46 | tokenTags = body.tokens[i].match(/tags=\[(.*)\]/)[1].split(',');
47 | tmpDictOjb = {};
48 | tmpDictOjb.tags0 = tokenTags[0];
49 | tmpDictOjb.tags1 = tokenTags[1].replace(/\s/,'');
50 | tmpDictOjb.tags6 = tokenTags[6].replace(/\s/,'');
51 | tokens.push(tmpDictOjb);
52 |
53 | }
54 | dictObj.patern = form.document;
55 | dictObj.tokens = tokens;
56 | console.log(JSON.stringify(dictObj,null,indentString));
57 | }
58 | });
59 |
--------------------------------------------------------------------------------
/ka-is-written-in-hiragana.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 参考
3 | // https://www.jtf.jp/jp/style_guide/pdf/jtf_style_guide.pdf
4 | // 2.2.3. 一部の助数詞の表記
5 | // 助数詞にともなう「ヵ」、「か」、「カ」、「ヶ」、「ケ」、「箇」、「個」の表記は、原則として、ひらがなの「か」を使います。
6 |
7 | var terms = [
8 | {
9 | 'expected':'か',
10 | 'pattern':['ヵ、カ、ヶ、ケ、箇、個'],
11 | 'tokenCheck':['名詞','接尾','[ヵカヶケ箇個][月所国年]']
12 | },
13 | {
14 | 'expected':'か月',
15 | 'pattern':['個月']
16 | }
17 | ];
18 |
19 | var tokenCheck = function (sentence){
20 | for (var k = 0; k < sentence.tokens.length; k++) {
21 | if (
22 | sentence.tokens[k].tags[0] === terms[i]['tokenCheck'][0] &&
23 | sentence.tokens[k].tags[1] === terms[i]['tokenCheck'][1] &&
24 | sentence.tokens[k].tags[6].match(new RegExp(terms[i]['tokenCheck'][2]))
25 | ){
26 | addError('「' + sentence.tokens[k].surface + '」を修正してください。助数詞にともなう「ヵかカヶケ箇個」の表記は、原則として、ひらがなの「か」を使います。' , sentence);
27 | }
28 | }
29 | }
30 |
31 | for ( var i = 0; i < terms.length; i++ ) {
32 | for ( var j = 0; j < terms[i]['pattern'].length; j++ ) {
33 | var regex = new RegExp( terms[i]['pattern'][j]);
34 | // 形態素解析するかどうか
35 | if ( 'tokenCheck' in terms[i] ) {
36 | tokenCheck(sentence);
37 | } else {
38 | if ( sentence.content.match(regex) ) {
39 | addError('「' + terms[i]['pattern'][j] + '」を「' + terms[i]['expected'] + '」に修正してください。助数詞にともなう「ヵかカヶケ箇個」の表記は、原則として、ひらがなの「か」を使います。', sentence);
40 | }
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/symbol.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 参考
3 | // https://www.jtf.jp/jp/style_guide/pdf/jtf_style_guide.pdf
4 | // 4.2. 記号
5 | // カタカナは「全角」で表記します。半角カタカナは特殊な用途を除いて、原則として使いません。
6 | var regex1 = new RegExp( /[()]/ );
7 | var regex2 = new RegExp( /[!!]/ );
8 | var regex3 = new RegExp( /[??]/ );
9 | var regex4 = new RegExp( /[^ァ-ンヲァ-ンヲ]・[^ァ-ンヲァ-ンヲ]/ );
10 | var regex5 = new RegExp( /[--]/ );
11 | var regex6 = new RegExp( /[:;:;]/ );
12 | var regex7 = new RegExp( /["”'’`‘{}{}<>]/ );
13 | var regexMail = new RegExp(/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*/);
14 | var regexTimes = new RegExp(/([01]?[0-9]|2[0-3])[::]([0-5][0-9])/);
15 | var regexTelNum = new RegExp(/\d{2,5}[-(]\d{1,4}[-)]\d{4}/)
16 | var regexAddress = new RegExp(/[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}/)
17 | var tmp = ''
18 | var mailResult = ''
19 |
20 | // 1センテンス内に複数のミスがある場合を考慮して、gつきでマッチさせて、複数回エラーを出した方がいい気がする。
21 | // しかし、複数回ミスがある場合に一つだけ修正すると、残ったミスがエラーとして改めて検知される。
22 | // したがって、とりあえずこのままとする。使ってみて違和感があったらG方式に変更する
23 | if ( sentence.content.match(regex1) ) {
24 | addError('丸かっこは全角を使います。', sentence);
25 | }
26 | if ( sentence.content.match(regex2) ) {
27 | addError('感嘆符の利用は避けてください。', sentence);
28 | }
29 | if ( sentence.content.match(regex3) ) {
30 | addError('疑問符の利用は避けてください。', sentence);
31 | }
32 | if ( sentence.content.match(regex4) ) {
33 | addError('カタカナ複合語の区切り以外で「・」の利用は避けてください。', sentence);
34 | }
35 |
36 | // Sentenceからメールアドレスを除外する
37 | tmp = sentence.content
38 | while ( regexMail.test(tmp) === true ){
39 | tmp = tmp.replace(regexMail,'')
40 | }
41 | if ( tmp.match(regex5) ){
42 | if ( !tmp.match(regexTelNum) && !tmp.match(regexAddress)){
43 | addError('原則として「' + tmp.match(regex5) + '」の利用は避けてください。', sentence);
44 | }
45 | }
46 |
47 | // Sentenceから時刻を除外する
48 | tmp = sentence.content
49 | while ( regexTimes.test(tmp) === true ){
50 | tmp = tmp.replace(regexTimes,'')
51 | }
52 | if ( tmp.match(regex6) ) {
53 | addError('原則として「' + sentence.content.match(regex6) + '」の利用は避けてください。もし利用せざるを得ない場合は全角を使います。', sentence);
54 | }
55 | if ( sentence.content.match(regex7) ) {
56 | addError('「' + sentence.content.match(regex7) + '」の利用は避けてください。', sentence);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/termsValidator.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 使い方はREADMEを参照ください。
3 | // https://github.com/kongou-ae/redpen-validator/blob/master/README.md
4 | /*
5 | console = {
6 | log:print
7 | };
8 | */
9 | var terms = [
10 | /* サンプル
11 | {
12 | 'expected':'ファイアウォール',
13 | 'pattern':['ファイアーウォール','ファイヤーウォール','ファイヤウォール','ファイヤーウオール'],
14 | 'source':'MyCompany'
15 | },
16 | {
17 | 'expected':'こと',
18 | 'pattern':['事'],
19 | 'tokenCheck':['名詞','非自立','事'],
20 | 'source':'MyCompany'
21 | },
22 | {
23 | 'expected':'なぜ',
24 | 'pattern':['何故'],
25 | 'source':'MyCompany'
26 | },
27 | {
28 | 'expected':'ちょうど',
29 | 'pattern':['丁度'],
30 | 'source':'MyCompany'
31 | },
32 | {
33 | 'expected':'なんでも',
34 | 'pattern':['何でも'],
35 | 'source':'MyCompany'
36 | },
37 | {
38 | 'expected':'通信事業者',
39 | 'pattern':['通信キャリア'],
40 | 'source':'MyCompany'
41 | }
42 | */
43 | ];
44 |
45 | var morphologicalAnalysis = function(sentence){
46 | for (var k = 0; k < sentence.tokens.length; k++) {
47 | if ( sentence.tokens[k].tags[0] === terms[i]['tokenCheck'][0] &&
48 | sentence.tokens[k].tags[1] === terms[i]['tokenCheck'][1] &&
49 | sentence.tokens[k].tags[6] === terms[i]['tokenCheck'][2] ){
50 | addError('文書規約違反(' + terms[i]['source'] + ')です。「' + sentence.tokens[k].surface + '」を修正してください。(正:' + terms[i]['expected'] + ' 誤:' + terms[i]['pattern'][j] + ')' , sentence);
51 | }
52 | }
53 | }
54 |
55 | for ( var i = 0; i < terms.length; i++ ) {
56 | for ( var j = 0; j < terms[i]['pattern'].length; j++ ) {
57 | var regex = new RegExp( terms[i]['pattern'][j]);
58 | if ( 'tokenCheck' in terms[i] ) {
59 | morphologicalAnalysis(sentence);
60 | } else {
61 | if ( sentence.content.match(regex) ) {
62 | addError('文書規約違反(' + terms[i]['source'] + ')です。「' + terms[i]['pattern'][j] + '」を「' + terms[i]['expected'] + '」に修正してください', sentence);
63 | }
64 | }
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/custom-pattern.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 |
3 | var terms = [
4 | /* // sample
5 | {
6 | 'pattern':'考えられる',
7 | 'message':'断定を避ける表現です。断定系を使ってください。',
8 | 'tokens':[
9 | {
10 | 'tags0':'動詞',
11 | 'tags1':'自立',
12 | 'tags6':'考える'
13 | },
14 | {
15 | 'tags0':'動詞',
16 | 'tags1':'接尾',
17 | 'tags6':'られる'
18 | }
19 | ]
20 | },
21 | {
22 | 'pattern':'ではないだろうか',
23 | 'message':'断定を避ける表現です。断定系を使ってください。',
24 | }
25 | */
26 | ];
27 |
28 | var validateRegex = function(sentence,terms){
29 | var regex = new RegExp( terms.pattern );
30 | if ( regex.test(sentence) ) {
31 | return 'error';
32 | }
33 | }
34 |
35 | var validateToken = function(sentence,terms){
36 |
37 | var result = 0;
38 | for (var i = 0; i < sentence.tokens.length; i++) {
39 | // 検査できる=今のTokenの位置+検査すべきTokenの数が検査すべきTokenの長さよりも小さい
40 | if ( i + terms.tokens.length - 1 < sentence.tokens.length ){
41 | // 判定用変数を初期化
42 | result = 0
43 | for (var j = 0; j < terms.tokens.length; j++){
44 | if (
45 | sentence.tokens[i+j].tags[0] === terms.tokens[j].tags0 &&
46 | sentence.tokens[i+j].tags[1] === terms.tokens[j].tags1 &&
47 | sentence.tokens[i+j].tags[6] === terms.tokens[j].tags6
48 | ){
49 | result++;
50 | }
51 | }
52 | if (result === terms.tokens.length){
53 | return 'error';
54 | }
55 | }
56 | }
57 |
58 | }
59 |
60 | var error = ''
61 | for (var j = 0; j < terms.length; j++) {
62 | if ( !terms[j].hasOwnProperty('tokens') ){
63 | error = validateRegex(sentence,terms[j]);
64 | }
65 |
66 | if ( terms[j].hasOwnProperty('tokens') ){
67 | error = validateToken(sentence,terms[j]);
68 | }
69 |
70 | if ( error ){
71 | addError( '「' + terms[j].pattern + '」は' + terms[j].message, sentence);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/use-hiragana-and-kanji-properly-v2.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 |
3 | var terms = [
4 | /* // sample
5 | {
6 | 'pattern':'考えられる',
7 | 'message':'断定を避ける表現です。断定系を使ってください。',
8 | 'tokens':[
9 | {
10 | 'tags0':'動詞',
11 | 'tags1':'自立',
12 | 'tags6':'考える'
13 | },
14 | {
15 | 'tags0':'動詞',
16 | 'tags1':'接尾',
17 | 'tags6':'られる'
18 | }
19 | ]
20 | },
21 | {
22 | 'pattern':'ではないだろうか',
23 | 'message':'断定を避ける表現です。断定系を使ってください。',
24 | }
25 | */
26 | {
27 | "patern": "上で",
28 | 'message':'「上で」を「うえで」に修正してください。',
29 | "tokens": [
30 | {
31 | "tags0": "名詞",
32 | "tags1": "非自立",
33 | "tags6": "上"
34 | },
35 | {
36 | "tags0": "助詞",
37 | "tags1": "格助詞",
38 | "tags6": "で"
39 | }
40 | ]
41 | }
42 | ];
43 |
44 | var validateRegex = function(sentence,terms){
45 | var regex = new RegExp( terms.pattern );
46 | if ( regex.test(sentence) ) {
47 | return 'error';
48 | }
49 | }
50 |
51 | var validateToken = function(sentence,terms){
52 |
53 | var result = 0;
54 | for (var i = 0; i < sentence.tokens.length; i++) {
55 | // 検査できる=今のTokenの位置+検査すべきTokenの数が検査すべきTokenの長さよりも小さい
56 | if ( i + terms.tokens.length - 1 < sentence.tokens.length ){
57 | // 判定用変数を初期化
58 | result = 0
59 | for (var j = 0; j < terms.tokens.length; j++){
60 | if (
61 | sentence.tokens[i+j].tags[0] === terms.tokens[j].tags0 &&
62 | sentence.tokens[i+j].tags[1] === terms.tokens[j].tags1 &&
63 | sentence.tokens[i+j].tags[6] === terms.tokens[j].tags6
64 | ){
65 | result++;
66 | }
67 | }
68 | if (result === terms.tokens.length){
69 | return 'error';
70 | }
71 | }
72 | }
73 |
74 | }
75 |
76 | var error = ''
77 | for (var j = 0; j < terms.length; j++) {
78 | if ( !terms[j].hasOwnProperty('tokens') ){
79 | error = validateRegex(sentence,terms[j]);
80 | }
81 |
82 | if ( terms[j].hasOwnProperty('tokens') ){
83 | error = validateToken(sentence,terms[j]);
84 | }
85 |
86 | if ( error ){
87 | addError( '「' + terms[j].pattern + '」は' + terms[j].message, sentence);
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # redpen-validator
2 |
3 | Javascript拡張を利用したRedPenのValidatorです。
4 |
5 |  [](https://codeclimate.com/github/kongou-ae/redpen-validator)
6 |
7 | # 使い方
8 |
9 | RedPenのコンフィグファイルに以下を追記します。
10 |
11 | ```xml
12 |
13 |
14 |
15 | ```
16 |
17 | ## 各ファイルが対応する検査項目
18 |
19 | |ファイル名 |検査項目 |参考文献 |
20 | |----------------------------|--------------------------|-----------------------|
21 | |use-joyo-Kanji.js |常用漢字を使っているか |JTF 日本語標準スタイルガイド(翻訳用) 2.1.2|
22 | |katakana-must-be-two-byte.js|全角のカタカナを使っているか |JTF 日本語標準スタイルガイド(翻訳用) 2.1.5|
23 | |numeral-must-be-hankaku.js |半角の算用数字を使っているか |JTF 日本語標準スタイルガイド(翻訳用) 2.1.8|
24 | |alphabet-must-be-one-byte.js|半角のアルファベットを使っているか |JTF 日本語標準スタイルガイド(翻訳用) 2.1.9|
25 | |use-hiragana-and-kanji-properly.js |ひらがなと漢字の使い分け|JTF 日本語標準スタイルガイド(翻訳用) 2.2.1|
26 | |use-numeral-properly.js |算用数字と漢数字の使い分け |JTF 日本語標準スタイルガイド(翻訳用) 2.2.2|
27 | |ka-is-written-in-hiragana.js|助数詞にともなう「か」の表記 |JTF 日本語標準スタイルガイド(翻訳用) 2.2.3|
28 | |symbol.js |記号の使い方が適切か |JTF 日本語標準スタイルガイド(翻訳用) 4.2 & 4.3|
29 | |use-assertive-style.js |断定を避ける表現 |use-assertive-style.js内に記載|
30 | |use-literary-style.js |口語表現 |use-literary-style.js内に記載 |
31 | |dont-use-kosoado.js |こそあど言葉 |dont-use-kosoado.js内に記載 |
32 | |dont-use-can-do.js |することができる |dont-use-can-do.js内に記載 |
33 | |custom-pattern.js |自分で登録した規則が含まれているか |なし
34 |
35 |
36 |
37 | ## custom-pattern.js
38 |
39 | 自分で表記の規則を登録して利用する拡張です。`terms`配列に登録されている表記の規則を利用して、文章に規則から外れた表現が含まれているかを検査します。検査方法は正規表現と形態素解析の二つをサポートしています。
40 |
41 | ### 正規表現による検査
42 |
43 | 正規表現による検査を行う場合、`terms`配列に以下パラメータを持ったオブジェクトを登録します。
44 |
45 | ```
46 | {
47 | 'pattern':'ではないだろうか',
48 | 'message':'断定を避ける表現です。断定系を使ってください。',
49 | }
50 | ```
51 |
52 | ### 形態素解析による検査
53 |
54 | 形態素解析による検査を行う場合、`terms`配列に以下プロパティを持ったオブジェクトを登録します。
55 |
56 | ```
57 | {
58 | 'pattern':'考えられる',
59 | 'message':'断定を避ける表現です。断定系を使ってください。',
60 | 'tokens':[
61 | {
62 | 'tags0':'動詞',
63 | 'tags1':'自立',
64 | 'tags6':'考える'
65 | },
66 | {
67 | 'tags0':'動詞',
68 | 'tags1':'接尾',
69 | 'tags6':'られる'
70 | }
71 | ]
72 | },
73 | ```
74 |
75 | `tokens`プロパティには、kuromojiによる形態素解析の結果を登録します。各項目とkuromojiによる形態素解析の結果は、以下の通り紐づいています。kuromojiによる形態素解析の結果は[kuromojiのデモサイト](http://atilika.org/kuromoji/)で取得するのが簡単です。
76 |
77 | |項目 |登録内容|
78 | |------|-------|
79 | |tags0 |`Part-of-Speech`の1つ目(kuromojiが生成するTokenに含まれるFeatureの1つ目)|
80 | |tags1 |`Part-of-Speech`の2つ目(kuromojiが生成するTokenに含まれるFeatureの2つ目)|
81 | |tags6 |`Base form`(kuromojiが生成するTokenに含まれるFeatureの7つ目)|
82 |
83 | ## 謝辞
84 |
85 | use-joyo-Kanji.jsの作成にあたっては、以下のサイトを参考にさせていただきました。感謝します。
86 |
87 | - [【みんなの知識 ちょっと便利帳】入力した文章・文字が常用漢字かどうかを調べる](http://www.benricho.org/kanji/kyoikukanji/check-jyoyo-kanji.html)
88 | - [漢字にマッチする JavaScript の正規表現パターン: Days on the Moon](http://nanto.asablo.jp/blog/2015/12/31/7966713)
89 |
--------------------------------------------------------------------------------
/dont-use-can-do.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 参考
3 | // http://www.slideshare.net/yoshinobumachida5/lets-write-understandable-japanese-complete-version
4 | // することができる問題
5 | var terms = [
6 | {
7 | "pattern": "することができる",
8 | "message": "冗長な表現です。",
9 | "tokens": [
10 | {
11 | "tags0": "動詞",
12 | "tags1": "自立",
13 | "tags6": "する"
14 | },
15 | {
16 | "tags0": "名詞",
17 | "tags1": "非自立",
18 | "tags6": "こと"
19 | },
20 | {
21 | "tags0": "助詞",
22 | "tags1": "格助詞",
23 | "tags6": "が"
24 | },
25 | {
26 | "tags0": "動詞",
27 | "tags1": "自立",
28 | "tags6": "できる"
29 | }
30 | ]
31 | },
32 | {
33 | "pattern": "することが出来る",
34 | "message": "冗長な表現です。",
35 | "tokens": [
36 | {
37 | "tags0": "動詞",
38 | "tags1": "自立",
39 | "tags6": "する"
40 | },
41 | {
42 | "tags0": "名詞",
43 | "tags1": "非自立",
44 | "tags6": "こと"
45 | },
46 | {
47 | "tags0": "助詞",
48 | "tags1": "格助詞",
49 | "tags6": "が"
50 | },
51 | {
52 | "tags0": "動詞",
53 | "tags1": "自立",
54 | "tags6": "出来る"
55 | }
56 | ]
57 | },
58 | {
59 | "pattern": "する事ができる",
60 | "message": "冗長な表現です。",
61 | "tokens": [
62 | {
63 | "tags0": "動詞",
64 | "tags1": "自立",
65 | "tags6": "する"
66 | },
67 | {
68 | "tags0": "名詞",
69 | "tags1": "非自立",
70 | "tags6": "事"
71 | },
72 | {
73 | "tags0": "助詞",
74 | "tags1": "格助詞",
75 | "tags6": "が"
76 | },
77 | {
78 | "tags0": "動詞",
79 | "tags1": "自立",
80 | "tags6": "できる"
81 | }
82 | ]
83 | },
84 | {
85 | "pattern": "することが出来る",
86 | "message": "冗長な表現です。",
87 | "tokens": [
88 | {
89 | "tags0": "動詞",
90 | "tags1": "自立",
91 | "tags6": "する"
92 | },
93 | {
94 | "tags0": "名詞",
95 | "tags1": "非自立",
96 | "tags6": "事"
97 | },
98 | {
99 | "tags0": "助詞",
100 | "tags1": "格助詞",
101 | "tags6": "が"
102 | },
103 | {
104 | "tags0": "動詞",
105 | "tags1": "自立",
106 | "tags6": "出来る"
107 | }
108 | ]
109 | }
110 | ];
111 |
112 | var validateRegex = function(sentence,terms){
113 | var regex = new RegExp( terms.pattern );
114 | if ( regex.test(sentence) ) {
115 | return 'error';
116 | }
117 | }
118 |
119 | var validateToken = function(sentence,terms){
120 | var result = 0;
121 | for (var i = 0; i < sentence.tokens.length; i++) {
122 | // 検査できる=今のTokenの位置+検査すべきTokenの数が検査すべきTokenの長さよりも小さい
123 | if ( i + terms.tokens.length - 1 < sentence.tokens.length ){
124 | // 判定用変数を初期化
125 | result = 0
126 | for (var j = 0; j < terms.tokens.length; j++){
127 | if (
128 | sentence.tokens[i+j].tags[0] === terms.tokens[j].tags0 &&
129 | sentence.tokens[i+j].tags[1] === terms.tokens[j].tags1 &&
130 | sentence.tokens[i+j].tags[6] === terms.tokens[j].tags6
131 | ){
132 | result++;
133 | }
134 | }
135 | if (result === terms.tokens.length){
136 | return 'error';
137 | }
138 | }
139 | }
140 | }
141 |
142 | var error = ''
143 | for (var j = 0; j < terms.length; j++) {
144 | if ( !terms[j].hasOwnProperty('tokens') ){
145 | error = validateRegex(sentence,terms[j]);
146 | }
147 |
148 | if ( terms[j].hasOwnProperty('tokens') ){
149 | error = validateToken(sentence,terms[j]);
150 | }
151 |
152 | if ( error ){
153 | addError( '「' + terms[j].pattern + '」は' + terms[j].message, sentence);
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/use-assertive-style.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 |
3 | var terms = [
4 | {
5 | 'pattern':'考えられる',
6 | 'message':'断定を避ける表現です。断定系を使ってください。',
7 | 'tokens':[
8 | {
9 | 'tags0':'動詞',
10 | 'tags1':'自立',
11 | 'tags6':'考える'
12 | },
13 | {
14 | 'tags0':'動詞',
15 | 'tags1':'接尾',
16 | 'tags6':'られる'
17 | }
18 | ]
19 | },
20 | {
21 | 'pattern':'が分かる',
22 | 'message':'断定を避ける表現です。断定系を使ってください。',
23 | 'tokens':[
24 | {
25 | 'tags0':'助詞',
26 | 'tags1':'格助詞',
27 | 'tags6':'が'
28 | },
29 | {
30 | 'tags0':'動詞',
31 | 'tags1':'自立',
32 | 'tags6':'分かる'
33 | }
34 | ]
35 | },
36 | {
37 | 'pattern':'がわかる',
38 | 'message':'断定を避ける表現です。断定系を使ってください。',
39 | 'tokens':[
40 | {
41 | 'tags0':'助詞',
42 | 'tags1':'格助詞',
43 | 'tags6':'が'
44 | },
45 | {
46 | 'tags0':'動詞',
47 | 'tags1':'自立',
48 | 'tags6':'わかる'
49 | }
50 | ]
51 | },
52 | {
53 | 'pattern':'と思う',
54 | 'message':'断定を避ける表現です。断定系を使ってください。',
55 | 'tokens':[
56 | {
57 | 'tags0':'助詞',
58 | 'tags1':'格助詞',
59 | 'tags6':'と'
60 | },
61 | {
62 | 'tags0':'動詞',
63 | 'tags1':'自立',
64 | 'tags6':'思う'
65 | }
66 | ]
67 | },
68 | {
69 | 'pattern':'かもしれない',
70 | 'message':'断定を避ける表現です。断定系を使ってください。',
71 | 'tokens':[
72 | {
73 | 'tags0':'助詞',
74 | 'tags1':'副助詞',
75 | 'tags6':'かも'
76 | },
77 | {
78 | 'tags0':'動詞',
79 | 'tags1':'自立',
80 | 'tags6':'しれる'
81 | },
82 | {
83 | 'tags0':'助動詞',
84 | 'tags1':'*',
85 | 'tags6':'ない'
86 | }
87 | ]
88 | },
89 | {
90 | 'pattern':'ではないだろうか',
91 | 'message':'断定を避ける表現です。断定系を使ってください。'
92 | },
93 | {
94 | 'pattern':'でしょう',
95 | 'message':'断定を避ける表現です。断定系を使ってください。'
96 | },
97 | {
98 | 'pattern':'と感じる',
99 | 'message':'断定を避ける表現です。断定系を使ってください。',
100 | 'tokens':[
101 | {
102 | 'tags0':'助詞',
103 | 'tags1':'格助詞',
104 | 'tags6':'と'
105 | },
106 | {
107 | 'tags0':'動詞',
108 | 'tags1':'自立',
109 | 'tags6':'感じる'
110 | }
111 | ]
112 | }
113 | ];
114 |
115 | var validateRegex = function(sentence,terms){
116 | var regex = new RegExp( terms.pattern );
117 | if ( regex.test(sentence) ) {
118 | return 'error';
119 | }
120 | }
121 |
122 | var validateToken = function(sentence,terms){
123 | var result = 0;
124 | for (var i = 0; i < sentence.tokens.length; i++) {
125 | // 検査できる=今のTokenの位置+検査すべきTokenの数が検査すべきTokenの長さよりも小さい
126 | if ( i + terms.tokens.length - 1 < sentence.tokens.length ){
127 | // 判定用変数を初期化
128 | result = 0
129 | for (var j = 0; j < terms.tokens.length; j++){
130 | // 過剰検知は先行でresultを減らすことで対処
131 | if (sentence.tokens[i+j].tags[6] === "わかる" && sentence.tokens[i+j+1].tags[0] === "形容詞"){ result--; }
132 | if (sentence.tokens[i+j].tags[6] === "分かる" && sentence.tokens[i+j+1].tags[0] === "形容詞"){ result--; }
133 |
134 | if (
135 | sentence.tokens[i+j].tags[0] === terms.tokens[j].tags0 &&
136 | sentence.tokens[i+j].tags[1] === terms.tokens[j].tags1 &&
137 | sentence.tokens[i+j].tags[6] === terms.tokens[j].tags6
138 | ){
139 | result++;
140 | }
141 | }
142 | if (result === terms.tokens.length){
143 | return 'error';
144 | }
145 | }
146 | }
147 | }
148 |
149 | var error = ''
150 | for (var j = 0; j < terms.length; j++) {
151 | if ( !terms[j].hasOwnProperty('tokens') ){
152 | error = validateRegex(sentence,terms[j]);
153 | }
154 |
155 | if ( terms[j].hasOwnProperty('tokens') ){
156 | error = validateToken(sentence,terms[j]);
157 | }
158 |
159 | if ( error ){
160 | addError( '「' + terms[j].pattern + '」は' + terms[j].message, sentence);
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/use-numeral-properly.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 参考
3 | // https://www.jtf.jp/jp/style_guide/pdf/jtf_style_guide.pdf
4 | // 2.2.2. 算用数字と漢数字の使い分け
5 | // 数量を表現し、数を数えられるものは算用数字を使用します。任意の数に置き換えても通用する語句がこれに該当します。序数詞(「第~回」「~番目」「~回目」)も算用数字を使います。
6 | var tmp = ''
7 | for (var k = 0; k < sentence.tokens.length; k++) {
8 |
9 | // --------------------------------------------------------------------------------------------
10 | // -漢数字にすべきなのに、算用数字になってしまうケースを除外する
11 | // --------------------------------------------------------------------------------------------
12 | // 3文字先までチェックして4文字熟語であれば、算用数字にしない(4個のTokenに分割されない4文字熟語は別途考える。。)
13 |
14 | if ( k + 3 < sentence.tokens.length ) {
15 | if (
16 | sentence.tokens[k].tags[6].match(/[一二三四五六七八九十百千]/) &&
17 | sentence.tokens[k+1].tags[6].match(/[\u4E00-\u9FFF]/) &&
18 | sentence.tokens[k+2].tags[6].match(/[一二三四五六七八九十百千]/) &&
19 | sentence.tokens[k+3].tags[6].match(/[\u4E00-\u9FFF]/)
20 | ) return null;
21 | }
22 |
23 | // 4文字にTokenされす3文字にTokenされる四文字熟語を算用数字にしない
24 | if ( k + 2 < sentence.tokens.length ) {
25 | tmp = sentence.tokens[k].surface + sentence.tokens[k+1].surface + sentence.tokens[k+2].surface;
26 | if ( tmp.match(/[一二三四五六七八九十百千][\u4E00-\u9FFF][一二三四五六七八九十百千][\u4E00-\u9FFF]/) ) return null;
27 | }
28 |
29 | // 4文字にTokenされす2文字にTokenされる四文字熟語を算用数字にしない
30 | if ( k + 1 < sentence.tokens.length ){
31 | tmp = sentence.tokens[k].surface + sentence.tokens[k+1].surface;
32 | if ( tmp.match(/[一二三四五六七八九十百千][\u4E00-\u9FFF][一二三四五六七八九十百千][\u4E00-\u9FFF]/) ) return null;
33 | }
34 |
35 | // 数[漢数字]が数[算用数字]になってしまうので除外
36 | if ( k + 1 < sentence.tokens.length ){
37 | if (
38 | sentence.tokens[k].tags[6] === '数' &&
39 | sentence.tokens[k+1].tags[6].match(/[十百千万]/)
40 | ) return null;
41 | }
42 |
43 | // [漢数字]次[名詞]
44 | if (k + 2 < sentence.tokens.length){
45 | if (
46 | sentence.tokens[k].tags[6].match(new RegExp(/[一二三四五六七八九十百千]/)) &&
47 | sentence.tokens[k+1].tags[6] === '次' &&
48 | sentence.tokens[k+2].tags[0] === '名詞'
49 | ) return null;
50 | }
51 |
52 | if( k + 1 < sentence.tokens.length ){
53 | if (
54 | sentence.tokens[k].surface === '五' &&
55 | sentence.tokens[k+1].tags[6] ==='大陸'
56 | ) return null;
57 | }
58 |
59 | // --------------------------------------------------------------------------------------------
60 | // 最後の処理で算用数字にすべきなのに、ならないケースを個別にエラー処理
61 | // --------------------------------------------------------------------------------------------
62 | // 漢数字を含む言葉が一つの単語としてtokenizeされてしまうになってしまうケース
63 | if ( sentence.tokens[k].tags[6].match(/十進法|二進法|十六進法/) ) return addError('数を数えられるものは算用数字を利用します' , sentence );
64 |
65 | // 三つが「三つ」という一般名詞でtokenizeされてしまうので、個別に定義
66 | if (
67 | sentence.tokens[k].tags[0] === "名詞" &&
68 | sentence.tokens[k].tags[1] === "一般" &&
69 | sentence.tokens[k].tags[6].match(new RegExp(/[一二三四五六七八九]つ/))
70 | ){
71 | addError('数を数えられるものは算用数字を利用します' , sentence );
72 | }
73 |
74 | // --------------------------------------------------------------------------------------------
75 | // 問答無用で算用数字にする処理
76 | // --------------------------------------------------------------------------------------------
77 | // 上記に合致せず、名詞で数のものがあれば、
78 | if (
79 | sentence.tokens[k].tags[0] === "名詞" &&
80 | sentence.tokens[k].tags[1] === "数" &&
81 | sentence.tokens[k].tags[6].match(new RegExp(/[一二三四五六七八九十百千]/))
82 | ){
83 | addError('数を数えられるものは算用数字を利用します' , sentence );
84 | }
85 |
86 | // --------------------------------------------------------------------------------------------
87 | // 漢数字にすべきケースに対してエラー処理
88 | // --------------------------------------------------------------------------------------------
89 | // [漢数字]大陸 算用数字の場合は、漢数字にするよう促す
90 | if ( k + 1 < sentence.tokens.length ){
91 | if (
92 | sentence.tokens[k].surface === '5' &&
93 | sentence.tokens[k+1].tags[6] ==='大陸'
94 | ) addError('慣用的表現、熟語、概数、固有名詞、副詞など、漢数字を使用することが一般的な語句では漢数字を使います。' , sentence );
95 | }
96 |
97 | // [算用数字]次[名詞]
98 | if ( k + 2 < sentence.tokens.length ){
99 | if (
100 | sentence.tokens[k].surface.match(new RegExp(/[1-9]/)) &&
101 | sentence.tokens[k+1].tags[6] === '次' &&
102 | sentence.tokens[k+2].tags[0] === '名詞'
103 | ) addError('慣用的表現、熟語、概数、固有名詞、副詞など、漢数字を使用することが一般的な語句では漢数字を使います。' , sentence );
104 | }
105 |
106 | // [算用数字]時的
107 | if ( k + 2 < sentence.tokens.length ){
108 | if (
109 | sentence.tokens[k].surface.match(new RegExp(/[1-9]/)) &&
110 | sentence.tokens[k+1].tags[6] === '時' &&
111 | sentence.tokens[k+2].tags[6] === '的'
112 | ) addError('慣用的表現、熟語、概数、固有名詞、副詞など、漢数字を使用することが一般的な語句では漢数字を使います。' , sentence );
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/use-literary-style.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 口語ではなく文語を使う
3 |
4 | var terms = [
5 | // http://www.ise.chuo-u.ac.jp/ISE/outline/Gmajor/nihongo/28.html
6 | {
7 | 'expected':'過度に',
8 | 'pattern':['あまりに']
9 | },
10 | {
11 | 'expected':'一度に/一括して/まとめて',
12 | 'pattern':['いっぺんに']
13 | },
14 | {
15 | 'expected':'また,さらに',
16 | 'pattern':['あと'],
17 | 'tokenCheck':['名詞','副詞可能','あと']
18 | },
19 | {
20 | 'expected':'行う/する',
21 | 'pattern':['やる'],
22 | 'tokenCheck':['動詞','自立','やる']
23 | },
24 | {
25 | 'expected':'する',
26 | 'pattern':['してやる'],
27 | 'tokenCheck':['動詞','自立','してやる']
28 | },
29 | // 別途検知方法を考える
30 | // してあげる、してない
31 | {
32 | 'expected':'が',
33 | 'pattern':['けど'],
34 | 'tokenCheck':['助詞','接続助詞','けど']
35 | },
36 | {
37 | 'expected':'であった',
38 | 'pattern':['だった']
39 | },
40 | {
41 | 'expected':'であるとき/であったらならば/なら',
42 | 'pattern':['だったら']
43 | },
44 | // 別途検知方法を考える
45 | // 文頭のシリーズ しようがない
46 | {
47 | 'expected':'のような',
48 | 'pattern':['みたいな']
49 | },
50 | {
51 | 'expected':'は/や',
52 | 'pattern':['とか'],
53 | 'tokenCheck':['助詞','並立助詞','とか']
54 | },
55 | // 別途検知方法を考える
56 | // したり
57 | {
58 | 'expected':'ではなく',
59 | 'pattern':['じゃなくて']
60 | },
61 | {
62 | 'expected':'適切な言葉',
63 | 'pattern':['すごく'],
64 | 'tokenCheck':['形容詞','自立','すごい']
65 | },
66 | // 別途検知方法を考える
67 | // したり
68 | {
69 | 'expected':'比較的/やや/かなり/たいへん/きわめて',
70 | 'pattern':['超'],
71 | 'tokenCheck':['接頭詞','名詞接続','超']
72 | },
73 | {
74 | 'expected':'真に/絶対的に/圧倒的に',
75 | 'pattern':['まじで']
76 | },
77 | {
78 | 'expected':'直接的に/直接',
79 | 'pattern':['まともに']
80 | },
81 | {
82 | 'expected':'直接的に/直接',
83 | 'pattern':['もろに']
84 | },
85 | {
86 | 'expected':'単純/易しい/容易',
87 | 'pattern':['簡単']
88 | },
89 | {
90 | 'expected':'単純/易しい/容易',
91 | 'pattern':['楽'],
92 | 'tokenCheck':['名詞','形容動詞語幹','楽']
93 | },
94 | {
95 | 'expected':'複雑/難しい/困難',
96 | 'pattern':['面倒']
97 | },
98 | {
99 | 'expected':'複雑/難しい/困難',
100 | 'pattern':['難儀']
101 | },
102 | {
103 | 'expected':'複雑/難しい/困難',
104 | 'pattern':['厄介']
105 | },
106 | // http://www.ipentec.com/document/document.aspx?page=write-thesis-tips
107 | /*
108 | {
109 | 'expected':'別の表現',
110 | 'pattern':['という'],
111 | 'tokenCheck':['助詞','格助詞','という']
112 | },
113 | */
114 | {
115 | 'expected':'別の表現',
116 | 'pattern':['すると']
117 | },
118 | // http://isabelle.cc.kyushu-u.ac.jp/~amano/how_to_write/japanese.html
119 | {
120 | 'expected':'する必要がある',
121 | 'pattern':['ないといけない']
122 | },
123 | {
124 | 'expected':'したがって/このため/そのため',
125 | 'pattern':['だから']
126 | },
127 | {
128 | 'expected':'したがって/このため/そのため',
129 | 'pattern':['それで']
130 | },
131 | // http://www.ise.chuo-u.ac.jp/ISE/outline/Gmajor/nihongo/50.html
132 | {
133 | 'expected':'済みません/申し訳ございません',
134 | 'pattern':['すいません']
135 | },
136 | {
137 | 'expected':'他の適切な表現',
138 | 'pattern':['ちなみに']
139 | },
140 | {
141 | 'expected':'ています',
142 | 'pattern':['てます']
143 | },
144 | {
145 | 'expected':'ていません',
146 | 'pattern':['てません']
147 | },
148 | {
149 | 'expected':'もの',
150 | 'pattern':['やつ'],
151 | 'tokenCheck':['名詞','代名詞','やつ']
152 | },
153 | {
154 | 'expected':'削除/他の適切な表現',
155 | 'pattern':['しまう'],
156 | 'tokenCheck':['動詞','非自立','しまう']
157 | }
158 | ];
159 |
160 | var morphologicalAnalysis = function(sentence){
161 | for (var k = 0; k < sentence.tokens.length; k++) {
162 | if ( sentence.tokens[k].tags[0] === terms[i]['tokenCheck'][0] &&
163 | sentence.tokens[k].tags[1] === terms[i]['tokenCheck'][1] &&
164 | sentence.tokens[k].tags[6] === terms[i]['tokenCheck'][2] ){
165 | addError('「' + terms[i]['pattern'][j] +'」は口語です。「' + terms[i]['expected'] + '」に修正してください' , sentence);
166 | }
167 | }
168 | }
169 |
170 | for ( var i = 0; i < terms.length; i++ ) {
171 | for ( var j = 0; j < terms[i]['pattern'].length; j++ ) {
172 | var regex = new RegExp( terms[i]['pattern'][j] );
173 | if ( 'tokenCheck' in terms[i] ) {
174 | morphologicalAnalysis(sentence);
175 | } else {
176 | if ( sentence.content.match(regex) ) {
177 | addError('「' + terms[i]['pattern'][j] +'」は口語です。「' + terms[i]['expected'] + '」に修正してください。' , sentence);
178 | }
179 | }
180 | }
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/dont-use-kosoado.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 参考
3 | // http://jubilee-web.jp/blog/archives/96
4 | var terms = [
5 | {
6 | "pattern": "これ",
7 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
8 | "tokens": [
9 | {
10 | "tags0": "名詞",
11 | "tags1": "代名詞",
12 | "tags6": "これ"
13 | }
14 | ]
15 | },
16 | {
17 | "pattern": "それ",
18 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
19 | "tokens": [
20 | {
21 | "tags0": "名詞",
22 | "tags1": "代名詞",
23 | "tags6": "それ"
24 | }
25 | ]
26 | },
27 | {
28 | "pattern": "あれ",
29 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
30 | "tokens": [
31 | {
32 | "tags0": "名詞",
33 | "tags1": "代名詞",
34 | "tags6": "あれ"
35 | }
36 | ]
37 | },
38 | {
39 | "pattern": "どれ",
40 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
41 | "tokens": [
42 | {
43 | "tags0": "名詞",
44 | "tags1": "代名詞",
45 | "tags6": "どれ"
46 | }
47 | ]
48 | },
49 | {
50 | "pattern": "この",
51 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
52 | "tokens": [
53 | {
54 | "tags0": "連体詞",
55 | "tags1": "*",
56 | "tags6": "この"
57 | }
58 | ]
59 | },
60 | {
61 | "pattern": "その",
62 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
63 | "tokens": [
64 | {
65 | "tags0": "連体詞",
66 | "tags1": "*",
67 | "tags6": "その"
68 | }
69 | ]
70 | },
71 | {
72 | "pattern": "あの",
73 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
74 | "tokens": [
75 | {
76 | "tags0": "連体詞",
77 | "tags1": "*",
78 | "tags6": "あの"
79 | }
80 | ]
81 | },
82 | {
83 | "pattern": "どの",
84 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
85 | "tokens": [
86 | {
87 | "tags0": "連体詞",
88 | "tags1": "*",
89 | "tags6": "どの"
90 | }
91 | ]
92 | },
93 | {
94 | "pattern": "ここ",
95 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
96 | "tokens": [
97 | {
98 | "tags0": "名詞",
99 | "tags1": "代名詞",
100 | "tags6": "ここ"
101 | }
102 | ]
103 | },
104 | {
105 | "pattern": "そこ",
106 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
107 | "tokens": [
108 | {
109 | "tags0": "名詞",
110 | "tags1": "代名詞",
111 | "tags6": "そこ"
112 | }
113 | ]
114 | },
115 | {
116 | "pattern": "あそこ",
117 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
118 | "tokens": [
119 | {
120 | "tags0": "名詞",
121 | "tags1": "代名詞",
122 | "tags6": "あそこ"
123 | }
124 | ]
125 | },
126 | {
127 | "pattern": "どこ",
128 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
129 | "tokens": [
130 | {
131 | "tags0": "名詞",
132 | "tags1": "代名詞",
133 | "tags6": "どこ"
134 | }
135 | ]
136 | },
137 | {
138 | "pattern": "こちら",
139 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
140 | "tokens": [
141 | {
142 | "tags0": "名詞",
143 | "tags1": "代名詞",
144 | "tags6": "こちら"
145 | }
146 | ]
147 | },
148 | {
149 | "pattern": "そちら",
150 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
151 | "tokens": [
152 | {
153 | "tags0": "名詞",
154 | "tags1": "代名詞",
155 | "tags6": "そちら"
156 | }
157 | ]
158 | },
159 | {
160 | "pattern": "あちら",
161 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
162 | "tokens": [
163 | {
164 | "tags0": "名詞",
165 | "tags1": "代名詞",
166 | "tags6": "あちら"
167 | }
168 | ]
169 | },
170 | {
171 | "pattern": "どちら",
172 | "message": "指示語です。指示語を使うと文章が分かりにくくなります。具体的な表現を検討してください。",
173 | "tokens": [
174 | {
175 | "tags0": "名詞",
176 | "tags1": "代名詞",
177 | "tags6": "どちら"
178 | }
179 | ]
180 | }
181 | ];
182 |
183 | var validateToken = function(sentence,terms){
184 |
185 | var result = 0;
186 | var count = 0;
187 | for (var i = 0; i < sentence.tokens.length; i++) {
188 | for (var j = 0; j < terms.length; j++) {
189 | // 検査できる=今のTokenの位置+検査すべきTokenの数が検査すべきTokenの長さよりも小さい
190 | if ( i + terms[j].tokens.length - 1 < sentence.tokens.length ){
191 | // 判定用変数を初期化
192 | // 規則にマッチしているかを一つずつチェック
193 | result = 0
194 | for (var k = 0; k < terms[j].tokens.length; k++){
195 | if (
196 | sentence.tokens[i+k].tags[0] === terms[j].tokens[k].tags0 &&
197 | sentence.tokens[i+k].tags[1] === terms[j].tokens[k].tags1 &&
198 | sentence.tokens[i+k].tags[6] === terms[j].tokens[k].tags6
199 | ){
200 | result++;
201 | }
202 | }
203 | // チェックした結果が規則の個数と一致したら、こそあどとみなす
204 | if (result === terms[j].tokens.length){
205 | count++;
206 | }
207 | }
208 | }
209 | }
210 | return count
211 | }
212 |
213 | var count = ''
214 | count = validateToken(sentence,terms);
215 |
216 | if ( count >= 2 ){
217 | addError( "複数のこそあど言葉が使われています。", sentence);
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/use-joyo-Kanji.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 参考
3 | // https://www.jtf.jp/jp/style_guide/pdf/jtf_style_guide.pdf
4 | // 2.1.2. 漢字
5 | // 漢字は「全角」で表記します。漢字の使用は、平成 22 年 11 月 30 日内閣告示第 2 号の「常用漢字表」に原則として準じます。
6 |
7 | // 参考
8 | // http://www.benricho.org/kanji/kyoikukanji/check-jyoyo-kanji.html
9 | // http://nanto.asablo.jp/blog/2015/12/31/7966713
10 |
11 | // http://www.benricho.org/kanji/kyoikukanji/check-jyoyo-kanji.html
12 | joyoKanji = ['亜','哀','挨','愛','曖','悪','握','圧','扱','宛','嵐','安','案','暗','以','衣','位','囲','医','依','委','威','為','畏','胃','尉','異','移','萎','偉','椅','彙','意','違','維','慰','遺','緯','域','育','一','壱','逸','茨','芋','引','印','因','咽','姻','員','院','淫','陰','飲','隠','韻','右','宇','羽','雨','唄','鬱','畝','浦','運','雲','永','泳','英','映','栄','営','詠','影','鋭','衛','易','疫','益','液','駅','悦','越','謁','閲','円','延','沿','炎','怨','宴','媛','援','園','煙','猿','遠','鉛','塩','演','縁','艶','汚','王','凹','央','応','往','押','旺','欧','殴','桜','翁','奥','横','岡','屋','億','憶','臆','虞','乙','俺','卸','音','恩','温','穏','下','化','火','加','可','仮','何','花','佳','価','果','河','苛','科','架','夏','家','荷','華','菓','貨','渦','過','嫁','暇','禍','靴','寡','歌','箇','稼','課','蚊','牙','瓦','我','画','芽','賀','雅','餓','介','回','灰','会','快','戒','改','怪','拐','悔','海','界','皆','械','絵','開','階','塊','楷','解','潰','壊','懐','諧','貝','外','劾','害','崖','涯','街','慨','蓋','該','概','骸','垣','柿','各','角','拡','革','格','核','殻','郭','覚','較','隔','閣','確','獲','嚇','穫','学','岳','楽','額','顎','掛','潟','括','活','喝','渇','割','葛','滑','褐','轄','且','株','釜','鎌','刈','干','刊','甘','汗','缶','完','肝','官','冠','巻','看','陥','乾','勘','患','貫','寒','喚','堪','換','敢','棺','款','間','閑','勧','寛','幹','感','漢','慣','管','関','歓','監','緩','憾','還','館','環','簡','観','韓','艦','鑑','丸','含','岸','岩','玩','眼','頑','顔','願','企','伎','危','机','気','岐','希','忌','汽','奇','祈','季','紀','軌','既','記','起','飢','鬼','帰','基','寄','規','亀','喜','幾','揮','期','棋','貴','棄','毀','旗','器','畿','輝','機','騎','技','宜','偽','欺','義','疑','儀','戯','擬','犠','議','菊','吉','喫','詰','却','客','脚','逆','虐','九','久','及','弓','丘','旧','休','吸','朽','臼','求','究','泣','急','級','糾','宮','救','球','給','嗅','窮','牛','去','巨','居','拒','拠','挙','虚','許','距','魚','御','漁','凶','共','叫','狂','京','享','供','協','況','峡','挟','狭','恐','恭','胸','脅','強','教','郷','境','橋','矯','鏡','競','響','驚','仰','暁','業','凝','曲','局','極','玉','巾','斤','均','近','金','菌','勤','琴','筋','僅','禁','緊','錦','謹','襟','吟','銀','区','句','苦','駆','具','惧','愚','空','偶','遇','隅','串','屈','掘','窟','熊','繰','君','訓','勲','薫','軍','郡','群','兄','刑','形','系','径','茎','係','型','契','計','恵','啓','掲','渓','経','蛍','敬','景','軽','傾','携','継','詣','慶','憬','稽','憩','警','鶏','芸','迎','鯨','隙','劇','撃','激','桁','欠','穴','血','決','結','傑','潔','月','犬','件','見','券','肩','建','研','県','倹','兼','剣','拳','軒','健','険','圏','堅','検','嫌','献','絹','遣','権','憲','賢','謙','鍵','繭','顕','験','懸','元','幻','玄','言','弦','限','原','現','舷','減','源','厳','己','戸','古','呼','固','股','虎','孤','弧','故','枯','個','庫','湖','雇','誇','鼓','錮','顧','五','互','午','呉','後','娯','悟','碁','語','誤','護','口','工','公','勾','孔','功','巧','広','甲','交','光','向','后','好','江','考','行','坑','孝','抗','攻','更','効','幸','拘','肯','侯','厚','恒','洪','皇','紅','荒','郊','香','候','校','耕','航','貢','降','高','康','控','梗','黄','喉','慌','港','硬','絞','項','溝','鉱','構','綱','酵','稿','興','衡','鋼','講','購','乞','号','合','拷','剛','傲','豪','克','告','谷','刻','国','黒','穀','酷','獄','骨','駒','込','頃','今','困','昆','恨','根','婚','混','痕','紺','魂','墾','懇','左','佐','沙','査','砂','唆','差','詐','鎖','座','挫','才','再','災','妻','采','砕','宰','栽','彩','採','済','祭','斎','細','菜','最','裁','債','催','塞','歳','載','際','埼','在','材','剤','財','罪','崎','作','削','昨','柵','索','策','酢','搾','錯','咲','冊','札','刷','刹','拶','殺','察','撮','擦','雑','皿','三','山','参','桟','蚕','惨','産','傘','散','算','酸','賛','残','斬','暫','士','子','支','止','氏','仕','史','司','四','市','矢','旨','死','糸','至','伺','志','私','使','刺','始','姉','枝','祉','肢','姿','思','指','施','師','恣','紙','脂','視','紫','詞','歯','嗣','試','詩','資','飼','誌','雌','摯','賜','諮','示','字','寺','次','耳','自','似','児','事','侍','治','持','時','滋','慈','辞','磁','餌','璽','鹿','式','識','軸','七','�','�','失','室','疾','執','湿','嫉','漆','質','実','芝','写','社','車','舎','者','射','捨','赦','斜','煮','遮','謝','邪','蛇','尺','借','酌','釈','爵','若','弱','寂','手','主','守','朱','取','狩','首','殊','珠','酒','腫','種','趣','寿','受','呪','授','需','儒','樹','収','囚','州','舟','秀','周','宗','拾','秋','臭','修','袖','終','羞','習','週','衆','集','愁','酬','醜','蹴','襲','十','汁','充','住','柔','重','従','渋','銃','獣','縦','叔','祝','宿','淑','粛','縮','塾','熟','出','述','術','俊','春','瞬','旬','巡','盾','准','殉','純','循','順','準','潤','遵','処','初','所','書','庶','暑','署','緒','諸','女','如','助','序','叙','徐','除','小','升','少','召','匠','床','抄','肖','尚','招','承','昇','松','沼','昭','宵','将','消','症','祥','称','笑','唱','商','渉','章','紹','訟','勝','掌','晶','焼','焦','硝','粧','詔','証','象','傷','奨','照','詳','彰','障','憧','衝','賞','償','礁','鐘','上','丈','冗','条','状','乗','城','浄','剰','常','情','場','畳','蒸','縄','壌','嬢','錠','譲','醸','色','拭','食','植','殖','飾','触','嘱','織','職','辱','尻','心','申','伸','臣','芯','身','辛','侵','信','津','神','唇','娠','振','浸','真','針','深','紳','進','森','診','寝','慎','新','審','震','薪','親','人','刃','仁','尽','迅','甚','陣','尋','腎','須','図','水','吹','垂','炊','帥','粋','衰','推','酔','遂','睡','穂','随','髄','枢','崇','数','据','杉','裾','寸','瀬','是','井','世','正','生','成','西','声','制','姓','征','性','青','斉','政','星','牲','省','凄','逝','清','盛','婿','晴','勢','聖','誠','精','製','誓','静','請','整','醒','税','夕','斥','石','赤','昔','析','席','脊','隻','惜','戚','責','跡','積','績','籍','切','折','拙','窃','接','設','雪','摂','節','説','舌','絶','千','川','仙','占','先','宣','専','泉','浅','洗','染','扇','栓','旋','船','戦','煎','羨','腺','詮','践','箋','銭','潜','線','遷','選','薦','繊','鮮','全','前','善','然','禅','漸','膳','繕','狙','阻','祖','租','素','措','粗','組','疎','訴','塑','遡','礎','双','壮','早','争','走','奏','相','荘','草','送','倉','捜','挿','桑','巣','掃','曹','曽','爽','窓','創','喪','痩','葬','装','僧','想','層','総','遭','槽','踪','操','燥','霜','騒','藻','造','像','増','憎','蔵','贈','臓','即','束','足','促','則','息','捉','速','側','測','俗','族','属','賊','続','卒','率','存','村','孫','尊','損','遜','他','多','汰','打','妥','唾','堕','惰','駄','太','対','体','耐','待','怠','胎','退','帯','泰','堆','袋','逮','替','貸','隊','滞','態','戴','大','代','台','第','題','滝','宅','択','沢','卓','拓','託','濯','諾','濁','但','達','脱','奪','棚','誰','丹','旦','担','単','炭','胆','探','淡','短','嘆','端','綻','誕','鍛','団','男','段','断','弾','暖','談','壇','地','池','知','値','恥','致','遅','痴','稚','置','緻','竹','畜','逐','蓄','築','秩','窒','茶','着','嫡','中','仲','虫','沖','宙','忠','抽','注','昼','柱','衷','酎','鋳','駐','著','貯','丁','弔','庁','兆','町','長','挑','帳','張','彫','眺','釣','頂','鳥','朝','貼','超','腸','跳','徴','嘲','潮','澄','調','聴','懲','直','勅','捗','沈','珍','朕','陳','賃','鎮','追','椎','墜','通','痛','塚','漬','坪','爪','鶴','低','呈','廷','弟','定','底','抵','邸','亭','貞','帝','訂','庭','逓','停','偵','堤','提','程','艇','締','諦','泥','的','笛','摘','滴','適','敵','溺','迭','哲','鉄','徹','撤','天','典','店','点','展','添','転','塡','田','伝','殿','電','斗','吐','妬','徒','途','都','渡','塗','賭','土','奴','努','度','怒','刀','冬','灯','当','投','豆','東','到','逃','倒','凍','唐','島','桃','討','透','党','悼','盗','陶','塔','搭','棟','湯','痘','登','答','等','筒','統','稲','踏','糖','頭','謄','藤','闘','騰','同','洞','胴','動','堂','童','道','働','銅','導','瞳','峠','匿','特','得','督','徳','篤','毒','独','読','栃','凸','突','届','屯','豚','頓','貪','鈍','曇','丼','那','奈','内','梨','謎','鍋','南','軟','難','二','尼','弐','匂','肉','虹','日','入','乳','尿','任','妊','忍','認','寧','熱','年','念','捻','粘','燃','悩','納','能','脳','農','濃','把','波','派','破','覇','馬','婆','罵','拝','杯','背','肺','俳','配','排','敗','廃','輩','売','倍','梅','培','陪','媒','買','賠','白','伯','拍','泊','迫','剝','舶','博','薄','麦','漠','縛','爆','箱','箸','畑','肌','八','鉢','発','髪','伐','抜','罰','閥','反','半','氾','犯','帆','汎','伴','判','坂','阪','板','版','班','畔','般','販','斑','飯','搬','煩','頒','範','繁','藩','晩','番','蛮','盤','比','皮','妃','否','批','彼','披','肥','非','卑','飛','疲','秘','被','悲','扉','費','碑','罷','避','尾','眉','美','備','微','鼻','膝','肘','匹','必','泌','筆','姫','百','氷','表','俵','票','評','漂','標','苗','秒','病','描','猫','品','浜','貧','賓','頻','敏','瓶','不','夫','父','付','布','扶','府','怖','阜','附','訃','負','赴','浮','婦','符','富','普','腐','敷','膚','賦','譜','侮','武','部','舞','封','風','伏','服','副','幅','復','福','腹','複','覆','払','沸','仏','物','粉','紛','雰','噴','墳','憤','奮','分','文','聞','丙','平','兵','併','並','柄','陛','閉','塀','幣','弊','蔽','餅','米','壁','璧','癖','別','蔑','片','辺','返','変','偏','遍','編','弁','便','勉','歩','保','哺','捕','補','舗','母','募','墓','慕','暮','簿','方','包','芳','邦','奉','宝','抱','放','法','泡','胞','俸','倣','峰','砲','崩','訪','報','蜂','豊','飽','褒','縫','亡','乏','忙','坊','妨','忘','防','房','肪','某','冒','剖','紡','望','傍','帽','棒','貿','貌','暴','膨','謀','頰','北','木','朴','牧','睦','僕','墨','撲','没','勃','堀','本','奔','翻','凡','盆','麻','摩','磨','魔','毎','妹','枚','昧','埋','幕','膜','枕','又','末','抹','万','満','慢','漫','未','味','魅','岬','密','蜜','脈','妙','民','眠','矛','務','無','夢','霧','娘','名','命','明','迷','冥','盟','銘','鳴','滅','免','面','綿','麺','茂','模','毛','妄','盲','耗','猛','網','目','黙','門','紋','問','冶','夜','野','弥','厄','役','約','訳','薬','躍','闇','由','油','喩','愉','諭','輸','癒','唯','友','有','勇','幽','悠','郵','湧','猶','裕','遊','雄','誘','憂','融','優','与','予','余','誉','預','幼','用','羊','妖','洋','要','容','庸','揚','揺','葉','陽','溶','腰','様','瘍','踊','窯','養','擁','謡','曜','抑','沃','浴','欲','翌','翼','拉','裸','羅','来','雷','頼','絡','落','酪','辣','乱','卵','覧','濫','藍','欄','吏','利','里','理','痢','裏','履','璃','離','陸','立','律','慄','略','柳','流','留','竜','粒','隆','硫','侶','旅','虜','慮','了','両','良','料','涼','猟','陵','量','僚','領','寮','療','瞭','糧','力','緑','林','厘','倫','輪','隣','臨','瑠','涙','累','塁','類','令','礼','冷','励','戻','例','鈴','零','霊','隷','齢','麗','暦','歴','列','劣','烈','裂','恋','連','廉','練','錬','呂','炉','賂','路','露','老','労','弄','郎','朗','浪','廊','楼','漏','籠','六','録','麓','論','和','話','賄','脇','惑','枠','湾','腕'];
13 |
14 | // http://nanto.asablo.jp/blog/2015/12/31/7966713
15 | var regex = new RegExp('(?:[\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u3005\u3007\u3021-\u3029\u3038-\u303B\u3400-\u4DB5\u4E00-\u9FCC\uF900-\uFA6D\uFA70-\uFAD9]|[\uD840-\uD868][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|[\uD86A-\uD86C][\uDC00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D])','g');
16 | // 文章中に漢字があるかどうかを正規表現で確認する
17 | var result = sentence.content.match(regex);
18 | // 漢字が格納されている配列内に、常用漢字があるかをチェックする
19 | if ( result !== null ) {
20 | for ( var k = 0; k < result.length; k++ ){
21 | if ( joyoKanji.indexOf(result[k]) == -1 ) {
22 | addError('「' + result[k] + '」は常用漢字ではありません。常用漢字を利用してください', sentence);
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/use-hiragana-and-kanji-properly.js:
--------------------------------------------------------------------------------
1 | function validateSentence(sentence) {
2 | // 参考
3 | // https://www.jtf.jp/jp/style_guide/pdf/jtf_style_guide.pdf
4 | // 2.2.1. ひらがなと漢字の使い分け
5 | // 漢字は「全角」で表記します。漢字の使用は、平成 22 年 11 月 30 日内閣告示第 2 号の「常用漢字表」に原則として準じます。
6 |
7 | var terms = [
8 | {
9 | 'expected':'あらかじめ',
10 | 'pattern':['予め']
11 | },
12 | { 'expected':'いずれ',
13 | 'pattern':['何れ']
14 | },
15 | {
16 | 'expected':'いつ',
17 | 'pattern':['何時'],
18 | 'tokenCheck':['名詞','代名詞','何時'] // この形で形態素解析される「何時」がすくない。何と時にTokenizeされる。。。
19 | },
20 | { 'expected':'おおよそ',
21 | 'pattern':['凡そ']
22 | },
23 | { 'expected':'かえって',
24 | 'pattern':['却って'],
25 | 'tokenCheck':['副詞','一般','却って']
26 | },
27 | { 'expected':'かつ',
28 | 'pattern':['且つ']
29 | },
30 | { 'expected':'かもしれない',
31 | 'pattern':['かも知れない']
32 | },
33 | {
34 | 'expected':'ください',
35 | 'pattern':['下さい'],
36 | 'tokenCheck':['動詞','非自立','下さる']
37 | },
38 | { 'expected':'これほど',
39 | 'pattern':['これ程']
40 | },
41 | { 'expected':'ご',
42 | 'pattern':['御'],
43 | 'tokenCheck':['接頭詞','名詞接続','御']
44 | },
45 | { 'expected':'子ども',
46 | 'pattern':['こども|子供']
47 | },
48 | {
49 | 'expected':'さらに',
50 | 'pattern':['更に'],
51 | 'tokenCheck':['副詞','助詞類接続','更に']
52 | },
53 | {
54 | 'expected':'しかし',
55 | 'pattern':['然し']
56 | },
57 | {
58 | 'expected':'しばらく',
59 | 'pattern':['暫く']
60 | },
61 | {
62 | 'expected':'すなわち',
63 | 'pattern':['即ち']
64 | },
65 | /* スタイルガイドにはあるが、実際に使うことはないと思うので削除
66 | {
67 | 'expected':'すべき',
68 | 'pattern':['可き'],
69 | },
70 | */
71 | {
72 | 'expected':'せっかく',
73 | 'pattern':['折角']
74 | },
75 | {
76 | 'expected':'たびたび',
77 | 'pattern':['度々']
78 | },
79 | {
80 | 'expected':'ただし',
81 | 'pattern':['但し'],
82 | 'tokenCheck':['接続詞','*','但し']
83 | },
84 | {
85 | 'expected':'たち',
86 | 'pattern':['達'],
87 | 'tokenCheck':['名詞','接尾','達'] //中々検知しないので、個別に下で定義。。。
88 | },
89 | {
90 | 'expected':'人たち',
91 | 'pattern':['人達'],
92 | 'tokenCheck':['名詞','一般','人達']
93 | },
94 | {
95 | 'expected':'できる',
96 | 'pattern':['出来る'],
97 | 'tokenCheck':['動詞','自立','出来る']
98 | },
99 | {
100 | 'expected':'どこ',
101 | 'pattern':['何処']
102 | },
103 | {
104 | 'expected':'ないし',
105 | 'pattern':['乃至']
106 | },
107 | {
108 | 'expected':'なお',
109 | 'pattern':['尚'],
110 | 'tokenCheck':['接続詞','*','尚']
111 | },
112 | {
113 | 'expected':'なかなか', //少々精度に不安あり
114 | 'pattern':['中々']
115 | },
116 | /*いい感じの形態素解析が思いつかないのでパス
117 | {
118 | 'expected':'ほど',
119 | 'pattern':['程'],
120 | },
121 | */
122 | {
123 | 'expected':'または',
124 | 'pattern':['又は'],
125 | 'tokenCheck':['接続詞','*','又は']
126 | },
127 | {
128 | 'expected':'むしろ',
129 | 'pattern':['寧ろ']
130 | },
131 | {
132 | 'expected':'めったに',
133 | 'pattern':['滅多に']
134 | },
135 | {
136 | 'expected':'もはや',
137 | 'pattern':['最早']
138 | },
139 | {
140 | 'expected':'もしくは',
141 | 'pattern':['若しくは']
142 | },
143 | {
144 | 'expected':'もって',
145 | 'pattern':['以て|以って']
146 | },
147 | {
148 | 'expected':'ように',
149 | 'pattern':['様に'],
150 | 'tokenCheck':['名詞','非自立','様']
151 | },
152 | {
153 | 'expected':'よほど',
154 | 'pattern':['余程']
155 | },
156 | // JTF-2.2.1 漢字で書く
157 | {
158 | 'expected':'一切',
159 | 'pattern':['いっさい']
160 | },
161 | {
162 | 'expected':'必ず',
163 | 'pattern':['かならず']
164 | },
165 | {
166 | 'expected':'大いに',
167 | 'pattern':['おおいに']
168 | },
169 | {
170 | 'expected':'強いて',
171 | 'pattern':['しいて'],
172 | 'tokenCheck':['副詞','一般','しいて']
173 | },
174 | /* いい感じの検知方法が見当たらないのでパス
175 | {
176 | 'expected':'中',
177 | 'pattern':['じゅう'],
178 | },
179 | */
180 | {
181 | 'expected':'時々',
182 | 'pattern':['ときどき'],
183 | 'tokenCheck':['副詞','一般','ときどき']
184 | },
185 | {
186 | 'expected':'何しろ',
187 | 'pattern':['なにしろ'],
188 | 'tokenCheck':['副詞','一般','なにしろ']
189 | },
190 | /* いい感じの検知方法が見当たらないのでパス
191 | {
192 | 'expected':'何も',
193 | 'pattern':['なにも'],
194 | },
195 | */
196 | {
197 | 'expected':'何らかの',
198 | 'pattern':['なんらかの'],
199 | 'tokenCheck':['連体詞','*','なんらかの']
200 | },
201 | {
202 | 'expected':'何とも',
203 | 'pattern':['なんとも'],
204 | 'tokenCheck':['副詞','一般','なんとも']
205 | },
206 | // JTF-2.2.1 漢字を使い分ける
207 | {
208 | 'expected':'箇所',
209 | 'pattern':['個所']
210 | },
211 | {
212 | 'expected':'箇条書き',
213 | 'pattern':['個条書き']
214 | },
215 | /* いい感じの検知方法が見当たらないのでパス
216 | {
217 | 'expected':'付属する',
218 | 'pattern':['附属する'],
219 | },
220 | */
221 | {
222 | 'expected':'摩耗',
223 | 'pattern':['磨耗']
224 | },
225 | {
226 | 'expected':'摩滅',
227 | 'pattern':['磨滅']
228 | },
229 | // JTF=2.2.1 品詞・意味で使い分ける
230 | {
231 | 'expected':'および',
232 | 'pattern':['及び'],
233 | 'tokenCheck':['接続詞','*','及び']
234 | },
235 | {
236 | 'expected':'及ぶ',
237 | 'pattern':['およぶ'],
238 | 'tokenCheck':['動詞','自立','およぶ']
239 | },
240 | {
241 | 'expected':'いたします',
242 | 'pattern':['致します'],
243 | 'tokenCheck':['動詞','非自立','致す']
244 | },
245 | {
246 | 'expected':'致す',
247 | 'pattern':['いたす'],
248 | 'tokenCheck':['動詞','自立','いたす']
249 | },
250 | {
251 | 'expected':'したがって',
252 | 'pattern':['従って'],
253 | 'tokenCheck':['接続詞','*','従って']
254 | },
255 | {
256 | 'expected':'従う',
257 | 'pattern':['したがう'],
258 | 'tokenCheck':['動詞','自立','したがう']
259 | },
260 | /* これは形態素解析でも無理だと思う。。。
261 | {
262 | 'expected':'出す',
263 | 'pattern':['だす'],
264 | },
265 | {
266 | 'expected':'だす',
267 | 'pattern':['出す'],
268 | },
269 | */
270 | {
271 | 'expected':'付く',
272 | 'pattern':['つく'],
273 | 'tokenCheck':['動詞','自立','つく']
274 | },
275 | /* 活気付くや凍り付くが、一つの単語でTokenizeされてしまうため、検知できない。
276 | {
277 | 'expected':'つき',
278 | 'pattern':['付き'],
279 | 'tokenCheck':['名詞','接尾','付き'] //手付きや目付きは一つの名詞になってしまうので検知できない。。。
280 | // 好み
281 | },
282 | {
283 | 'expected':'とおり',
284 | 'pattern':['通り'],
285 | 'tokenCheck':['名詞','非自立','通り'] //「以下の通り」の通りは「名詞・一般」になってしまう。これを対象にしてしまうと、道路を意味する「通り」が平仮名になってしまう。。。
286 | },
287 | */
288 | {
289 | 'expected':'以下のとおり',
290 | 'pattern':['以下の通り'] // とりあえずこれは検知したいので個別に。
291 | },
292 | {
293 | 'expected':'通り',
294 | 'pattern':['とおり'],
295 | 'tokenCheck':['名詞','接尾','とおり']
296 | },
297 | {
298 | 'expected':'ほしい',
299 | 'pattern':['欲しい'],
300 | 'tokenCheck':['形容詞','非自立','欲しい']
301 | },
302 | {
303 | 'expected':'欲しい',
304 | 'pattern':['ほしい'],
305 | 'tokenCheck':['形容詞','自立','ほしい']
306 | },
307 | // JTF=2.2.1 複数の表記方法が一般的で、実務文書で頻出する語
308 | {
309 | 'expected':'あまりに',
310 | 'pattern':['余りに']
311 | },
312 | {
313 | 'expected':'きわめて',
314 | 'pattern':['極めて']
315 | },
316 | {
317 | 'expected':'さまざま',
318 | 'pattern':['様々']
319 | },
320 | {
321 | 'expected':'すでに',
322 | 'pattern':['既に']
323 | },
324 | {
325 | 'expected':'すべて',
326 | 'pattern':['全て']
327 | },
328 | {
329 | 'expected':'ともに',
330 | 'pattern':['共に'],
331 | 'tokenCheck':['副詞','一般','共に']
332 | },
333 | {
334 | 'expected':'たとえば',
335 | 'pattern':['例えば']
336 | },
337 | {
338 | 'expected':'ただちに',
339 | 'pattern':['直ちに']
340 | },
341 | {
342 | 'expected':'とうてい',
343 | 'pattern':['到底']
344 | },
345 | {
346 | 'expected':'はたして',
347 | 'pattern':['果たして']
348 | },
349 | {
350 | 'expected':'ひときわ',
351 | 'pattern':['一際']
352 | },
353 | /* kuromojiのテストツールが、「一度」を「ひとたび」と認識しないので対応できない
354 | {
355 | 'expected':'ひとたび',
356 | 'pattern':['一度'],
357 | },
358 | */
359 | {
360 | 'expected':'ほか',
361 | 'pattern':['他'],
362 | 'tokenCheck':['名詞','一般','他'] // 他を探す
363 | },
364 | {
365 | 'expected':'ほか',
366 | 'pattern':['他'],
367 | 'tokenCheck':['名詞','非自立','他'] // この他に必要なもの
368 | },
369 | {
370 | 'expected':'ほか',
371 | 'pattern':['外'],
372 | 'tokenCheck':['名詞','副詞可能','外'] // 思いの外が他でTokenizeされない。。。
373 | },
374 | {
375 | 'expected':'思いのほか',
376 | 'pattern':['思いの外']
377 | },
378 | {
379 | 'expected':'ほかならぬ',
380 | 'pattern':['他ならぬ|外ならぬ']
381 | },
382 | {
383 | 'expected':'まったく',
384 | 'pattern':['全く']
385 | },
386 | {
387 | 'expected':'もともと',
388 | 'pattern':['元々']
389 | },
390 | {
391 | 'expected':'わかる',
392 | 'pattern':['分かる'],
393 | 'tokenCheck':['動詞','自立','分かる']
394 | },
395 | {
396 | 'expected':'わかる',
397 | 'pattern':['解る'],
398 | 'tokenCheck':['動詞','自立','解る']
399 | },
400 | {
401 | 'expected':'わかる',
402 | 'pattern':['判る'],
403 | 'tokenCheck':['動詞','自立','判る']
404 | },
405 | {
406 | 'expected':'ひとつひとつ',
407 | 'pattern':['一つ一つ']
408 | },
409 | {
410 | 'expected':'わたし',
411 | 'pattern':['私'],
412 | 'tokenCheck':['名詞','代名詞','私']
413 | },
414 | {
415 | 'expected':'われわれ',
416 | 'pattern':['我々'],
417 | 'tokenCheck':['名詞','代名詞','我々']
418 | },
419 | // 過剰検知しそう。適宜形態素解析に切り替える
420 | {
421 | 'expected':'わが',
422 | 'pattern':['我が']
423 | }
424 | ];
425 |
426 | var tokenCheck = function (sentence){
427 | for (var k = 0; k < sentence.tokens.length; k++) {
428 | // 2.2.1
429 | if ( sentence.tokens[k].tags[0] === terms[i]['tokenCheck'][0] &&
430 | sentence.tokens[k].tags[1] === terms[i]['tokenCheck'][1] &&
431 | sentence.tokens[k].tags[6].match(new RegExp(terms[i]['tokenCheck'][2])) ){
432 | addError(' 「' + sentence.tokens[k].surface + '」を「' + terms[i]['expected'] + '」に修正してください' , sentence);
433 | }
434 | }
435 | }
436 |
437 | for ( var i = 0; i < terms.length; i++ ) {
438 | for ( var j = 0; j < terms[i]['pattern'].length; j++ ) {
439 | var regex = new RegExp( terms[i]['pattern'][j]);
440 | // 形態素解析するかどうか
441 | if ( 'tokenCheck' in terms[i] ) {
442 | tokenCheck(sentence);
443 | } else {
444 | if ( sentence.content.match(regex) ) {
445 | addError('「' + terms[i]['pattern'][j] + '」を「' + terms[i]['expected'] + '」に修正してください', sentence);
446 | }
447 | }
448 | }
449 | }
450 | }
451 |
--------------------------------------------------------------------------------