Skip to content

Commit 2e6507e

Browse files
authored
test: add linting integration tests (#16)
1 parent 7045852 commit 2e6507e

32 files changed

+279
-3
lines changed

bun.lockb

54.3 KB
Binary file not shown.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"@types/node": "^20.12.2",
3838
"bun-types": "latest",
3939
"esbuild": "^0.20.2",
40+
"textlint-rule-preset-ja-technical-writing": "^12.0.2",
4041
"textlint-scripts": "^14.0.4",
4142
"textlint-tester": "^14.0.4",
4243
"typescript": "^5.4.3",
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
= textlint for Typst
2+
3+
== sentence-length
4+
5+
あいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえお。
6+
7+
== max-comma
8+
9+
組版処理システムの例としては、Tex (LaTeX), SATySFi, Typst, Twight, SILEなどがあります。
10+
11+
== max-ten
12+
13+
これは、これは、これは、これは、これはだめ。
14+
15+
== max-kanji-continuous-len
16+
17+
情報処理学会は、電気学会、照明学会、応用物理学会、映像情報メディア学会および電子情報通信学会とともに電気系6学会の1つに数えられる存在です。
18+
19+
== arabic-kanji-numbers
20+
21+
Fibonacci数列の十番目の項は55です。
22+
23+
1時的なファイルは`/tmp`に保存されます。
24+
25+
== no-mix-dearu-desumasu
26+
27+
今日はいい天気ですね。今日はいい天気である。
28+
29+
== no-mixed-period
30+
31+
これは問題ないです。
32+
33+
「これはセリフ」
34+
35+
english only
36+
37+
これは句点がありません
38+
39+
== no-double-negative-ja
40+
41+
それが事件の発端だったといえなくもない。
42+
43+
確かにそういった懸念はない事はない。
44+
45+
== no-dropping-the-ra
46+
47+
お刺身を食べれない。
48+
49+
== no-doubled-conjunctive-particle-ga
50+
51+
今日は早朝から出発したが、定刻には間に合わなかったが、無事会場に到着した。
52+
53+
== no-doubled-conjunction
54+
55+
かな漢字変換により漢字が多用される傾向がある。しかし漢字の多用が読みにくさをもたらす側面は否定できない。しかし、平仮名が多い文は間延びした印象を与える恐れもある。
56+
57+
== no-doubled-joshi
58+
59+
私は彼は好きだ。
60+
61+
== no-nfd
62+
63+
ホ゜ケット エンシ゛ン。
64+
65+
== no-exclamation-question-mark
66+
67+
技術文書では、感嘆符、疑問符は基本的には使用しないでください!
68+
69+
== no-hankaku-kana
70+
71+
半角カタカナを使用しないでください。
72+
73+
== no-weak-phrase
74+
75+
この表現には問題があるかもしれないです。
76+
77+
== no-successive-word
78+
79+
これは問題ない文章です。
80+
81+
これはは問題ある文章です。
82+
83+
これは問題あるある文章です。
84+
85+
== no-abusage
86+
87+
ウインドウ幅が可変すると、レイアウトが崩れる。
88+
89+
今朝起きた事件に法律を適応する。
90+
91+
== no-redundant-expression
92+
93+
これは省略することが可能です。
94+
95+
== ja-unnatural-alphabet
96+
97+
リイr−ス。
98+
99+
== no-unmatched-pair
100+
101+
これは(秘密)です。

test/integration/linting.test.ts

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
3+
import {
4+
TextlintKernel,
5+
type TextlintKernelRule,
6+
type TextlintResult,
7+
} from "@textlint/kernel";
8+
// @ts-expect-error
9+
import { rules, rulesConfig } from "textlint-rule-preset-ja-technical-writing";
10+
11+
import { beforeAll, describe, expect, it } from "vitest";
12+
13+
import typstPlugin from "../../src";
14+
15+
describe("linting", () => {
16+
describe("smoke tests", () => {
17+
describe("textlint-rule-preset-ja-technical-writing", () => {
18+
let textlintResult: TextlintResult;
19+
20+
beforeAll(async () => {
21+
const kernel = new TextlintKernel();
22+
textlintResult = await kernel.lintText(
23+
fs.readFileSync(
24+
path.join(
25+
__dirname,
26+
"./fixtures/smoke/textlint-rule-preset-ja-technical-writing/main.typ",
27+
),
28+
"utf-8",
29+
),
30+
{
31+
ext: ".typ",
32+
plugins: [
33+
{
34+
pluginId: "typst",
35+
plugin: typstPlugin,
36+
},
37+
],
38+
rules: [
39+
// Set each rule in the preset individually
40+
...Object.entries(rules).map(
41+
([id, rule]) =>
42+
({
43+
ruleId: `ja-technical-writing/${id}`,
44+
rule: rule,
45+
options: rulesConfig[id] || true,
46+
}) as TextlintKernelRule,
47+
),
48+
],
49+
},
50+
);
51+
});
52+
53+
// Rule test configurations
54+
const ruleTests = [
55+
{
56+
ruleId: "sentence-length",
57+
expectedMessage: "exceeds the maximum sentence length",
58+
},
59+
{
60+
ruleId: "max-ten",
61+
expectedMessage: '一つの文で"、"を4つ以上使用',
62+
},
63+
{
64+
ruleId: "max-kanji-continuous-len",
65+
expectedMessage: "漢字が7つ以上連続",
66+
},
67+
{
68+
ruleId: "no-mix-dearu-desumasu",
69+
expectedMessage: '"ですます"調 でなければなりません',
70+
},
71+
{
72+
ruleId: "ja-no-mixed-period",
73+
expectedMessage: '文末が"。"で終わっていません',
74+
},
75+
{
76+
ruleId: "no-doubled-joshi",
77+
expectedMessage: "一文に二回以上利用されている助詞",
78+
},
79+
{
80+
ruleId: "no-dropping-the-ra",
81+
expectedMessage: "ら抜き言葉を使用",
82+
},
83+
{
84+
ruleId: "no-doubled-conjunctive-particle-ga",
85+
expectedMessage: '逆接の接続助詞 "が" が二回以上使われています',
86+
},
87+
{
88+
ruleId: "no-doubled-conjunction",
89+
expectedMessage: "同じ接続詞(しかし)が連続",
90+
},
91+
{
92+
ruleId: "no-exclamation-question-mark",
93+
expectedMessage: 'Disallow to use "!"',
94+
},
95+
{
96+
ruleId: "no-hankaku-kana",
97+
expectedMessage: "Disallow to use 半角カタカナ",
98+
},
99+
{
100+
ruleId: "ja-no-weak-phrase",
101+
expectedMessage: '弱い表現: "かも" が使われています',
102+
},
103+
{
104+
ruleId: "ja-no-successive-word",
105+
expectedMessage: "が連続して2回使われています",
106+
},
107+
{
108+
ruleId: "ja-no-redundant-expression",
109+
expectedMessage: 'することが可能です"は冗長な表現',
110+
},
111+
{
112+
ruleId: "ja-unnatural-alphabet",
113+
expectedMessage: "不自然なアルファベット",
114+
},
115+
{
116+
ruleId: "no-unmatched-pair",
117+
expectedMessage: "Cannot find a pairing character for (",
118+
},
119+
];
120+
121+
// Special cases with multiple expected messages
122+
const multiMessageTests = [
123+
{
124+
ruleId: "arabic-kanji-numbers",
125+
expectedMessages: ["十番目 => 10番目", "1時的 => 一時的"],
126+
},
127+
{
128+
ruleId: "no-double-negative-ja",
129+
expectedMessages: [
130+
"二重否定: 〜なくもない",
131+
"二重否定: 〜ないことはない",
132+
],
133+
},
134+
{
135+
ruleId: "no-nfd",
136+
expectedMessages: ['ホ゜" => "ポ"', 'シ゛" => "ジ"'],
137+
},
138+
{
139+
ruleId: "ja-no-abusage",
140+
expectedMessages: ["可変する", "適用"],
141+
},
142+
];
143+
144+
const getViolations = (ruleId: string) => {
145+
return textlintResult.messages.filter(
146+
(message) => message.ruleId === `ja-technical-writing/${ruleId}`,
147+
);
148+
};
149+
150+
// Single message tests
151+
for (const { ruleId, expectedMessage } of ruleTests) {
152+
it(`should detect ${ruleId} violations`, () => {
153+
const violations = getViolations(ruleId);
154+
expect(violations.length).toBeGreaterThan(0);
155+
expect(violations[0].message).toContain(expectedMessage);
156+
});
157+
}
158+
159+
// Multi-message tests
160+
for (const { ruleId, expectedMessages } of multiMessageTests) {
161+
it(`should detect ${ruleId} violations`, () => {
162+
const violations = getViolations(ruleId);
163+
expect(violations.length).toBeGreaterThan(0);
164+
165+
for (const expectedMessage of expectedMessages) {
166+
expect(
167+
violations.some((v) => v.message.includes(expectedMessage)),
168+
).toBe(true);
169+
}
170+
});
171+
}
172+
});
173+
});
174+
});
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)