Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
io-monad committed Feb 26, 2016
0 parents commit 7307ae2
Show file tree
Hide file tree
Showing 9 changed files with 393 additions and 0 deletions.
1 change: 1 addition & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "presets": ["es2015"] }
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
40 changes: 40 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Babel output
/lib

# Created by https://www.gitignore.io/api/node

### Node ###
# Logs
logs
*.log
npm-debug.log*

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules
jspm_packages

# Optional npm cache directory
.npm

# Optional REPL history
.node_repl_history
19 changes: 19 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2016 IRIDE Monad <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
64 changes: 64 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# textlint-rule-general-novel-style-ja

[textlint](https://github.com/textlint/textlint) rule to follow general style of Japanese novels.

日本の小説における一般的な作法に従うための textlint ルールです。

## インストール

npm install textlint-rule-general-novel-style-ja

## 使い方

$ npm install textlint textlint-rule-max-ten
$ textlint --rule general-novel-style-ja README.md

## 設定

`.textlintrc` に設定を記述します。詳しくは textlint のドキュメントを参照してください。

以下がデフォルトの設定です。

```js
{
"rules": {
"general-novel-style-ja": {
// 各段落の先頭に許可する文字
"chars_leading_paragraph": " 「『【〈《((“\"‘'[[〔{{<<",
// 閉じ括弧の手前に句読点(。、)を置かない
"no_punctuation_at_closing_quote": true,
// 疑問符(?)と感嘆符(!)の直後にスペースを置く
"space_after_marks": true,
// 連続した三点リーダー(…)の数は偶数にする
"even_number_ellipsises": true,
// 連続したダッシュ(―)の数は偶数にする
"even_number_dashes": true,
// 連続した中黒(・)を許可しない
"appropriate_use_of_interpunct": true,
// 連続した長音符(ー)を許可しない
"appropriate_use_of_choonpu": true,
// マイナス記号(−)は数字の前にしか許可しない
"appropriate_use_of_minus_sign": true,
// アラビア数字の桁数は2桁まで (false: チェックしない)
"max_arabic_numeral_digits": 2
}
}
}
```

## テスト

npm test

## Contributing

1. Fork it!
2. Create your feature branch: `git checkout -b my-new-feature`
3. Commit your changes: `git commit -am 'Add some feature'`
4. Push to the branch: `git push origin my-new-feature`
5. Submit a pull request :D

## License

MIT (See LICENSE)

43 changes: 43 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "textlint-rule-general-novel-style-ja",
"version": "1.0.0",
"description": "textlint rule to follow general style of Japanese novels",
"author": "IRIDE Monad <[email protected]>",
"license": "MIT",
"homepage": "https://github.com/io-monad/textlint-rule-general-novel-style-ja",
"repository": "io-monad/textlint-rule-general-novel-style-ja",
"bugs": {
"url": "https://github.com/io-monad/textlint-rule-general-novel-style-ja/issues"
},
"main": "lib/general-novel-style.js",
"scripts": {
"build": "babel src -d lib --source-maps",
"watch": "babel src -d lib --watch --source-maps",
"prepublish": "npm run --if-present build",
"test": "mocha"
},
"files": [
"src"
],
"directories": {
"test": "test"
},
"keywords": [
"textlint",
"rule",
"japanese",
"novel"
],
"devDependencies": {
"babel-cli": "^6.5.1",
"babel-preset-es2015": "^6.5.0",
"espower-babel": "^4.0.1",
"mocha": "^2.4.5",
"power-assert": "^1.2.0",
"textlint": "^5.3.1",
"textlint-tester": "^0.4.1"
},
"dependencies": {
"textlint-rule-helper": "^1.1.5"
}
}
113 changes: 113 additions & 0 deletions src/general-novel-style.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"use strict";

import {RuleHelper} from "textlint-rule-helper";

const defaultOptions = {
// 各段落の先頭に許可する文字
"chars_leading_paragraph": " 「『【〈《((“\"‘'[[〔{{<<",
// 閉じ括弧の手前に句読点(。、)を置かない
"no_punctuation_at_closing_quote": true,
// 疑問符(?)と感嘆符(!)の直後にスペースを置く
"space_after_marks": true,
// 連続した三点リーダー(…)の数は偶数にする
"even_number_ellipsises": true,
// 連続したダッシュ(―)の数は偶数にする
"even_number_dashes": true,
// 連続した中黒(・)を許可しない
"appropriate_use_of_interpunct": true,
// 連続した長音符(ー)を許可しない
"appropriate_use_of_choonpu": true,
// マイナス記号(−)は数字の前にしか許可しない
"appropriate_use_of_minus_sign": true,
// アラビア数字の桁数は2桁まで (false: チェックしない)
"max_arabic_numeral_digits": 2
};

export default function (context, options = {}) {
let opts = {};
Object.keys(defaultOptions).forEach((key) => {
opts[key] = options.hasOwnProperty(key) ? options[key] : defaultOptions[key];
});
const charsLeadingParagraph = (opts["chars_leading_paragraph"] || "").split("");
const noPunctuationAtClosingQuote = opts["no_punctuation_at_closing_quote"];
const spaceAfterMarks = opts["space_after_marks"];
const evenNumberEllipsises = opts["even_number_ellipsises"];
const evenNumberDashes = opts["even_number_dashes"];
const appropriateUseOfInterpunct = opts["appropriate_use_of_interpunct"];
const appropriateUseOfChoonpu = opts["appropriate_use_of_choonpu"];
const appropriateUseOfMinusSign = opts["appropriate_use_of_minus_sign"];
const maxArabicNumeralDigits = opts["max_arabic_numeral_digits"];

let helper = new RuleHelper(context);
let {Syntax, RuleError, report, getSource} = context;
return {
[Syntax.Paragraph](node) {
if (helper.isChildNode(node, [Syntax.BlockQuote])) {
return;
}

return new Promise((resolve, reject) => {
const text = getSource(node);

if (charsLeadingParagraph.length > 0) {
if (charsLeadingParagraph.indexOf(text.charAt(0)) == -1) {
report(node, new RuleError(`段落の先頭に許可されていない文字が存在しています`));
}
}

if (noPunctuationAtClosingQuote) {
if (/[。、][」』】〉》)\)”"’']\]〕}\}>>]/.test(text)) {
report(node, new RuleError("句読点(。、)が閉じ括弧の直前に存在しています"));
}
}

if (spaceAfterMarks) {
if (/[?!](?![ ?!」』】〉》)\)”"’']\]〕}\}>>]|$)/.test(text)) {
report(node, new RuleError("感嘆符(!)・疑問符(?)の直後にスペースか閉じ括弧が必要です"));
}
}

if (evenNumberEllipsises) {
let matches1 = text.match(/…+/g);
if (matches1 && matches1.some((s) => { return s.length % 2 == 1 })) {
report(node, new RuleError("連続した三点リーダー(…)の数が偶数ではありません"));
}
}

if (evenNumberDashes) {
let matches2 = text.match(/―+/g);
if (matches2 && matches2.some((s) => { return s.length % 2 == 1 })) {
report(node, new RuleError("連続したダッシュ(―)の数が偶数ではありません"));
}
}

if (appropriateUseOfInterpunct) {
if (/・・+/.test(text)) {
report(node, new RuleError("連続した中黒(・)が使われています"));
}
}

if (appropriateUseOfChoonpu) {
if (/ーー+/.test(text)) {
report(node, new RuleError("連続した長音符(ー)が使われています"))
}
}

if (appropriateUseOfMinusSign) {
if (/−(?![0-90123456789〇一二三四五六七八九十])/.test(text)) {
report(node, new RuleError("マイナス記号(−)の直後が数字ではありません"));
}
}

if (typeof maxArabicNumeralDigits == "number") {
let matches3 = text.match(/[0-90123456789]+/g);
if (matches3 && matches3.some((s) => { return s.length > maxArabicNumeralDigits })) {
report(node, new RuleError(`${maxArabicNumeralDigits}桁を超えるアラビア数字が使われています`));
}
}

resolve();
});
}
};
}
100 changes: 100 additions & 0 deletions test/general-novel-style-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"use strict";

import rule from "../src/general-novel-style";

var TextLintTester = require("textlint-tester");
var tester = new TextLintTester();
tester.run("general-novel-style", rule, {
valid: [
" 日本語の小説のテストです。日本語の小説の、テストなんです。",
"「こんにちは、世界」",
"「これはペンですか? いや、ペンであるはずがない!」",
"「…………なん……だと……」",
"『一体いつから――――ペンであると錯覚していた――?』",
" ヘロー・ワールド!",
" 2−3=−1",
{
text: "#日本語の小説のテストです。",
options: { "chars_leading_paragraph": "#" }
},
{
text: "「こんにちは、世界。」",
options: { "no_punctuation_at_closing_quote": false }
},
{
text: "「これはペンですか?いや、ペンであるはずがない!」",
options: { "space_after_marks": false }
},
{
text: "「………なん…だと…」",
options: { "even_number_ellipsises": false }
},
{
text: "『一体いつから―――ペンであると錯覚していた――?』",
options: { "even_number_dashes": false }
},
{
text: " ヘロー・・・ワールド・・・",
options: { "appropriate_use_of_interpunct": false }
},
{
text: " ヘローーーー・ワーーーールド",
options: { "appropriate_use_of_choonpu": false }
},
{
text: " ヘロ−・ワ−ルド",
options: { "appropriate_use_of_minus_sign": false }
},
{
text: " 1234+321=1555",
options: { "max_arabic_numeral_digits": false }
},
{
text: " 1234+321=1555",
options: { "max_arabic_numeral_digits": 4 }
}
],
invalid: [
{
text: "#日本語の小説のテストです。",
errors: [{ message: "段落の先頭に許可されていない文字が存在しています" }]
},
{
text: "「こんにちは、世界。」",
errors: [{ message: "句読点(。、)が閉じ括弧の直前に存在しています" }]
},
{
text: "「これはペンですか?いや、ペンであるはずがない!」",
errors: [{ message: "感嘆符(!)・疑問符(?)の直後にスペースか閉じ括弧が必要です" }]
},
{
text: "「………なん…だと…」",
errors: [{ message: "連続した三点リーダー(…)の数が偶数ではありません" }]
},
{
text: "『一体いつから―――ペンであると錯覚していた――?』",
errors: [{ message: "連続したダッシュ(―)の数が偶数ではありません" }]
},
{
text: " ヘロー・・・ワールド・・・",
errors: [{ message: "連続した中黒(・)が使われています" }]
},
{
text: " ヘローーーー・ワーーーールド",
errors: [{ message: "連続した長音符(ー)が使われています" }]
},
{
text: " ヘロ−・ワ−ルド",
errors: [{ message: "マイナス記号(−)の直後が数字ではありません" }]
},
{
text: " 1234+321=1555",
errors: [{ message: "2桁を超えるアラビア数字が使われています" }]
},
{
text: " 1234+321=1555",
options: { "max_arabic_numeral_digits": 3 },
errors: [{ message: "3桁を超えるアラビア数字が使われています" }]
}
]
});
Loading

0 comments on commit 7307ae2

Please sign in to comment.