From 9594ab9733b0aec28d300987cbbbbc00d39a7c15 Mon Sep 17 00:00:00 2001 From: 3w36zj6 <52315048+3w36zj6@users.noreply.github.com> Date: Mon, 19 May 2025 04:52:58 +0900 Subject: [PATCH 1/5] chore(deps): add textlint-rule-preset-ja-technical-writing to devDependencies --- bun.lockb | Bin 211494 -> 267117 bytes package.json | 1 + 2 files changed, 1 insertion(+) diff --git a/bun.lockb b/bun.lockb index 609201514dcf42fc662606ab53fee3a989ac4cda..5dbe839e6372c4bc8876403904cdc61d57308674 100755 GIT binary patch delta 63931 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 Pn$!H899Go%oaz4nKbJml diff --git a/package.json b/package.json index f4b2d43..76df5ad 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@types/node": "^20.12.2", "bun-types": "latest", "esbuild": "^0.20.2", + "textlint-rule-preset-ja-technical-writing": "^12.0.2", "textlint-scripts": "^14.0.4", "textlint-tester": "^14.0.4", "typescript": "^5.4.3", From 319f798dc8baa84a698df059c01e04280fe740cb Mon Sep 17 00:00:00 2001 From: 3w36zj6 <52315048+3w36zj6@users.noreply.github.com> Date: Sun, 1 Jun 2025 06:31:59 +0900 Subject: [PATCH 2/5] refactor: move unit test files to `unit` directory --- test/{ => unit}/example.typ | 0 test/{ => unit}/fixtures/Break/input.typ | 0 test/{ => unit}/fixtures/Break/output.json | 0 test/{ => unit}/fixtures/Code/input.typ | 0 test/{ => unit}/fixtures/Code/output.json | 0 test/{ => unit}/fixtures/CodeBlock/input.typ | 0 test/{ => unit}/fixtures/CodeBlock/output.json | 0 test/{ => unit}/fixtures/Comment/input.typ | 0 test/{ => unit}/fixtures/Comment/output.json | 0 test/{ => unit}/fixtures/Emphasis/input.typ | 0 test/{ => unit}/fixtures/Emphasis/output.json | 0 test/{ => unit}/fixtures/Header/input.typ | 0 test/{ => unit}/fixtures/Header/output.json | 0 test/{ => unit}/fixtures/Link/input.typ | 0 test/{ => unit}/fixtures/Link/output.json | 0 test/{ => unit}/fixtures/Strong/input.typ | 0 test/{ => unit}/fixtures/Strong/output.json | 0 test/{ => unit}/fixtures/empty-file/input.typ | 0 test/{ => unit}/fixtures/empty-file/output.json | 0 test/{ => unit}/fixtures/start-with-single-newline/input.typ | 0 test/{ => unit}/fixtures/start-with-single-newline/output.json | 0 test/{ => unit}/paragraphizedTextlintAstObject.json | 0 test/{ => unit}/parsing.test.ts | 2 +- test/{ => unit}/rawTypstAstObject.json | 0 test/{ => unit}/rawTypstAstString.txt | 0 test/{ => unit}/textlintAstObject.json | 0 test/{ => unit}/typstToTextlintAst.test.ts | 2 +- test/{ => unit}/update-fixtures.ts | 2 +- 28 files changed, 3 insertions(+), 3 deletions(-) rename test/{ => unit}/example.typ (100%) rename test/{ => unit}/fixtures/Break/input.typ (100%) rename test/{ => unit}/fixtures/Break/output.json (100%) rename test/{ => unit}/fixtures/Code/input.typ (100%) rename test/{ => unit}/fixtures/Code/output.json (100%) rename test/{ => unit}/fixtures/CodeBlock/input.typ (100%) rename test/{ => unit}/fixtures/CodeBlock/output.json (100%) rename test/{ => unit}/fixtures/Comment/input.typ (100%) rename test/{ => unit}/fixtures/Comment/output.json (100%) rename test/{ => unit}/fixtures/Emphasis/input.typ (100%) rename test/{ => unit}/fixtures/Emphasis/output.json (100%) rename test/{ => unit}/fixtures/Header/input.typ (100%) rename test/{ => unit}/fixtures/Header/output.json (100%) rename test/{ => unit}/fixtures/Link/input.typ (100%) rename test/{ => unit}/fixtures/Link/output.json (100%) rename test/{ => unit}/fixtures/Strong/input.typ (100%) rename test/{ => unit}/fixtures/Strong/output.json (100%) rename test/{ => unit}/fixtures/empty-file/input.typ (100%) rename test/{ => unit}/fixtures/empty-file/output.json (100%) rename test/{ => unit}/fixtures/start-with-single-newline/input.typ (100%) rename test/{ => unit}/fixtures/start-with-single-newline/output.json (100%) rename test/{ => unit}/paragraphizedTextlintAstObject.json (100%) rename test/{ => unit}/parsing.test.ts (89%) rename test/{ => unit}/rawTypstAstObject.json (100%) rename test/{ => unit}/rawTypstAstString.txt (100%) rename test/{ => unit}/textlintAstObject.json (100%) rename test/{ => unit}/typstToTextlintAst.test.ts (98%) rename test/{ => unit}/update-fixtures.ts (86%) diff --git a/test/example.typ b/test/unit/example.typ similarity index 100% rename from test/example.typ rename to test/unit/example.typ diff --git a/test/fixtures/Break/input.typ b/test/unit/fixtures/Break/input.typ similarity index 100% rename from test/fixtures/Break/input.typ rename to test/unit/fixtures/Break/input.typ diff --git a/test/fixtures/Break/output.json b/test/unit/fixtures/Break/output.json similarity index 100% rename from test/fixtures/Break/output.json rename to test/unit/fixtures/Break/output.json diff --git a/test/fixtures/Code/input.typ b/test/unit/fixtures/Code/input.typ similarity index 100% rename from test/fixtures/Code/input.typ rename to test/unit/fixtures/Code/input.typ diff --git a/test/fixtures/Code/output.json b/test/unit/fixtures/Code/output.json similarity index 100% rename from test/fixtures/Code/output.json rename to test/unit/fixtures/Code/output.json diff --git a/test/fixtures/CodeBlock/input.typ b/test/unit/fixtures/CodeBlock/input.typ similarity index 100% rename from test/fixtures/CodeBlock/input.typ rename to test/unit/fixtures/CodeBlock/input.typ diff --git a/test/fixtures/CodeBlock/output.json b/test/unit/fixtures/CodeBlock/output.json similarity index 100% rename from test/fixtures/CodeBlock/output.json rename to test/unit/fixtures/CodeBlock/output.json diff --git a/test/fixtures/Comment/input.typ b/test/unit/fixtures/Comment/input.typ similarity index 100% rename from test/fixtures/Comment/input.typ rename to test/unit/fixtures/Comment/input.typ diff --git a/test/fixtures/Comment/output.json b/test/unit/fixtures/Comment/output.json similarity index 100% rename from test/fixtures/Comment/output.json rename to test/unit/fixtures/Comment/output.json diff --git a/test/fixtures/Emphasis/input.typ b/test/unit/fixtures/Emphasis/input.typ similarity index 100% rename from test/fixtures/Emphasis/input.typ rename to test/unit/fixtures/Emphasis/input.typ diff --git a/test/fixtures/Emphasis/output.json b/test/unit/fixtures/Emphasis/output.json similarity index 100% rename from test/fixtures/Emphasis/output.json rename to test/unit/fixtures/Emphasis/output.json diff --git a/test/fixtures/Header/input.typ b/test/unit/fixtures/Header/input.typ similarity index 100% rename from test/fixtures/Header/input.typ rename to test/unit/fixtures/Header/input.typ diff --git a/test/fixtures/Header/output.json b/test/unit/fixtures/Header/output.json similarity index 100% rename from test/fixtures/Header/output.json rename to test/unit/fixtures/Header/output.json diff --git a/test/fixtures/Link/input.typ b/test/unit/fixtures/Link/input.typ similarity index 100% rename from test/fixtures/Link/input.typ rename to test/unit/fixtures/Link/input.typ diff --git a/test/fixtures/Link/output.json b/test/unit/fixtures/Link/output.json similarity index 100% rename from test/fixtures/Link/output.json rename to test/unit/fixtures/Link/output.json diff --git a/test/fixtures/Strong/input.typ b/test/unit/fixtures/Strong/input.typ similarity index 100% rename from test/fixtures/Strong/input.typ rename to test/unit/fixtures/Strong/input.typ diff --git a/test/fixtures/Strong/output.json b/test/unit/fixtures/Strong/output.json similarity index 100% rename from test/fixtures/Strong/output.json rename to test/unit/fixtures/Strong/output.json diff --git a/test/fixtures/empty-file/input.typ b/test/unit/fixtures/empty-file/input.typ similarity index 100% rename from test/fixtures/empty-file/input.typ rename to test/unit/fixtures/empty-file/input.typ diff --git a/test/fixtures/empty-file/output.json b/test/unit/fixtures/empty-file/output.json similarity index 100% rename from test/fixtures/empty-file/output.json rename to test/unit/fixtures/empty-file/output.json diff --git a/test/fixtures/start-with-single-newline/input.typ b/test/unit/fixtures/start-with-single-newline/input.typ similarity index 100% rename from test/fixtures/start-with-single-newline/input.typ rename to test/unit/fixtures/start-with-single-newline/input.typ diff --git a/test/fixtures/start-with-single-newline/output.json b/test/unit/fixtures/start-with-single-newline/output.json similarity index 100% rename from test/fixtures/start-with-single-newline/output.json rename to test/unit/fixtures/start-with-single-newline/output.json diff --git a/test/paragraphizedTextlintAstObject.json b/test/unit/paragraphizedTextlintAstObject.json similarity index 100% rename from test/paragraphizedTextlintAstObject.json rename to test/unit/paragraphizedTextlintAstObject.json diff --git a/test/parsing.test.ts b/test/unit/parsing.test.ts similarity index 89% rename from test/parsing.test.ts rename to test/unit/parsing.test.ts index 7ac485d..a071371 100644 --- a/test/parsing.test.ts +++ b/test/unit/parsing.test.ts @@ -3,7 +3,7 @@ import path from "node:path"; // parse all fixture and should has import { test } from "@textlint/ast-tester"; import { describe, expect, it } from "vitest"; -import { convertTypstSourceToTextlintAstObject } from "../src/typstToTextlintAst"; +import { convertTypstSourceToTextlintAstObject } from "../../src/typstToTextlintAst"; describe("parsing", () => { const fixtureDir = path.join(__dirname, "fixtures"); diff --git a/test/rawTypstAstObject.json b/test/unit/rawTypstAstObject.json similarity index 100% rename from test/rawTypstAstObject.json rename to test/unit/rawTypstAstObject.json diff --git a/test/rawTypstAstString.txt b/test/unit/rawTypstAstString.txt similarity index 100% rename from test/rawTypstAstString.txt rename to test/unit/rawTypstAstString.txt diff --git a/test/textlintAstObject.json b/test/unit/textlintAstObject.json similarity index 100% rename from test/textlintAstObject.json rename to test/unit/textlintAstObject.json diff --git a/test/typstToTextlintAst.test.ts b/test/unit/typstToTextlintAst.test.ts similarity index 98% rename from test/typstToTextlintAst.test.ts rename to test/unit/typstToTextlintAst.test.ts index ddf366f..a565ee9 100644 --- a/test/typstToTextlintAst.test.ts +++ b/test/unit/typstToTextlintAst.test.ts @@ -9,7 +9,7 @@ import { extractRawSourceByLocation, getRawTypstAstString, paragraphizeTextlintAstObject, -} from "../src/typstToTextlintAst"; +} from "../../src/typstToTextlintAst"; const typstSource = fs.readFileSync( path.join(__dirname, "example.typ"), diff --git a/test/update-fixtures.ts b/test/unit/update-fixtures.ts similarity index 86% rename from test/update-fixtures.ts rename to test/unit/update-fixtures.ts index f609d49..acdedad 100644 --- a/test/update-fixtures.ts +++ b/test/unit/update-fixtures.ts @@ -1,7 +1,7 @@ import fs from "node:fs"; import path from "node:path"; import { test } from "@textlint/ast-tester"; -import { convertTypstSourceToTextlintAstObject } from "../src/typstToTextlintAst"; +import { convertTypstSourceToTextlintAstObject } from "../../src/typstToTextlintAst"; const fixtureDir = path.join(__dirname, "fixtures"); for (const filePath of fs.readdirSync(fixtureDir)) { From d79d656fdeed9d2ac19de418e2297c3c1e26976a Mon Sep 17 00:00:00 2001 From: 3w36zj6 <52315048+3w36zj6@users.noreply.github.com> Date: Sun, 1 Jun 2025 21:05:59 +0900 Subject: [PATCH 3/5] test: add linting integration tests --- .../main.typ | 101 +++++++ test/integration/linting.test.ts | 267 ++++++++++++++++++ 2 files changed, 368 insertions(+) create mode 100644 test/integration/fixtures/smoke/textlint-rule-preset-ja-technical-writing/main.typ create mode 100644 test/integration/linting.test.ts diff --git a/test/integration/fixtures/smoke/textlint-rule-preset-ja-technical-writing/main.typ b/test/integration/fixtures/smoke/textlint-rule-preset-ja-technical-writing/main.typ new file mode 100644 index 0000000..069ac9d --- /dev/null +++ b/test/integration/fixtures/smoke/textlint-rule-preset-ja-technical-writing/main.typ @@ -0,0 +1,101 @@ += textlint for Typst + +== sentence-length + +あいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえお。 + +== max-comma + +組版処理システムの例としては、Tex (LaTeX), SATySFi, Typst, Twight, SILEなどがあります。 + +== max-ten + +これは、これは、これは、これは、これはだめ。 + +== max-kanji-continuous-len + +情報処理学会は、電気学会、照明学会、応用物理学会、映像情報メディア学会および電子情報通信学会とともに電気系6学会の1つに数えられる存在です。 + +== arabic-kanji-numbers + +Fibonacci数列の十番目の項は55です。 + +1時的なファイルは`/tmp`に保存されます。 + +== no-mix-dearu-desumasu + +今日はいい天気ですね。今日はいい天気である。 + +== no-mixed-period + +これは問題ないです。 + +「これはセリフ」 + +english only + +これは句点がありません + +== no-double-negative-ja + +それが事件の発端だったといえなくもない。 + +確かにそういった懸念はない事はない。 + +== no-dropping-the-ra + +お刺身を食べれない。 + +== no-doubled-conjunctive-particle-ga + +今日は早朝から出発したが、定刻には間に合わなかったが、無事会場に到着した。 + +== no-doubled-conjunction + +かな漢字変換により漢字が多用される傾向がある。しかし漢字の多用が読みにくさをもたらす側面は否定できない。しかし、平仮名が多い文は間延びした印象を与える恐れもある。 + +== no-doubled-joshi + +私は彼は好きだ。 + +== no-nfd + +ホ゜ケット エンシ゛ン。 + +== no-exclamation-question-mark + +技術文書では、感嘆符、疑問符は基本的には使用しないでください! + +== no-hankaku-kana + +半角カタカナを使用しないでください。 + +== no-weak-phrase + +この表現には問題があるかもしれないです。 + +== no-successive-word + +これは問題ない文章です。 + +これはは問題ある文章です。 + +これは問題あるある文章です。 + +== no-abusage + +ウインドウ幅が可変すると、レイアウトが崩れる。 + +今朝起きた事件に法律を適応する。 + +== no-redundant-expression + +これは省略することが可能です。 + +== ja-unnatural-alphabet + +リイr−ス。 + +== no-unmatched-pair + +これは(秘密)です。 diff --git a/test/integration/linting.test.ts b/test/integration/linting.test.ts new file mode 100644 index 0000000..95686a7 --- /dev/null +++ b/test/integration/linting.test.ts @@ -0,0 +1,267 @@ +import fs from "node:fs"; +import path from "node:path"; +import { + TextlintKernel, + type TextlintKernelRule, + type TextlintResult, +} from "@textlint/kernel"; +// @ts-expect-error +import { rules } from "textlint-rule-preset-ja-technical-writing"; + +import { beforeAll, describe, expect, it } from "vitest"; + +import typstPlugin from "../../src"; + +describe("linting", () => { + describe("smoke tests", () => { + describe("textlint-rule-preset-ja-technical-writing", () => { + let textlintResult: TextlintResult; + + beforeAll(async () => { + const kernel = new TextlintKernel(); + textlintResult = await kernel.lintText( + fs.readFileSync( + path.join( + __dirname, + "./fixtures/smoke/textlint-rule-preset-ja-technical-writing/main.typ", + ), + "utf-8", + ), + { + ext: ".typ", + plugins: [ + { + pluginId: "typst", + plugin: typstPlugin, + }, + ], + rules: [ + // Set each rule in the preset individually + ...Object.entries(rules).map( + ([id, rule]) => + ({ + ruleId: `ja-technical-writing/${id}`, + rule: rule, + }) as TextlintKernelRule, + ), + ], + }, + ); + }); + + it("should detect sentence-length violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/sentence-length", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain( + "exceeds the maximum sentence length", + ); + }); + + it("should detect max-ten violations", () => { + const violations = textlintResult.messages.filter( + (message) => message.ruleId === "ja-technical-writing/max-ten", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain('一つの文で"、"を4つ以上使用'); + }); + + it("should detect max-kanji-continuous-len violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/max-kanji-continuous-len", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain("漢字が6つ以上連続"); + }); + + it("should detect arabic-kanji-numbers violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/arabic-kanji-numbers", + ); + expect(violations.length).toBeGreaterThan(0); + expect( + violations.some((v) => v.message.includes("十番目 => 10番目")), + ).toBe(true); + expect( + violations.some((v) => v.message.includes("1時的 => 一時的")), + ).toBe(true); + }); + + it("should detect no-mix-dearu-desumasu violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/no-mix-dearu-desumasu", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain( + 'である"調 と "ですます"調 が混在', + ); + }); + + it("should detect ja-no-mixed-period violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/ja-no-mixed-period", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain('文末が"。"で終わっていません'); + }); + + it("should detect no-double-negative-ja violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/no-double-negative-ja", + ); + expect(violations.length).toBeGreaterThan(0); + expect( + violations.some((v) => v.message.includes("二重否定: 〜なくもない")), + ).toBe(true); + expect( + violations.some((v) => + v.message.includes("二重否定: 〜ないことはない"), + ), + ).toBe(true); + }); + + it("should detect no-doubled-joshi violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/no-doubled-joshi", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain( + "一文に二回以上利用されている助詞", + ); + }); + + it("should detect no-dropping-the-ra violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/no-dropping-the-ra", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain("ら抜き言葉を使用"); + }); + + it("should detect no-doubled-conjunctive-particle-ga violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === + "ja-technical-writing/no-doubled-conjunctive-particle-ga", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain( + '逆接の接続助詞 "が" が二回以上使われています', + ); + }); + + it("should detect no-doubled-conjunction violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/no-doubled-conjunction", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain("同じ接続詞(しかし)が連続"); + }); + + it("should detect no-nfd violations", () => { + const violations = textlintResult.messages.filter( + (message) => message.ruleId === "ja-technical-writing/no-nfd", + ); + expect(violations.length).toBeGreaterThan(0); + expect( + violations.some((v) => v.message.includes('ホ゜" => "ポ"')), + ).toBe(true); + expect( + violations.some((v) => v.message.includes('シ゛" => "ジ"')), + ).toBe(true); + }); + + it("should detect no-exclamation-question-mark violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === + "ja-technical-writing/no-exclamation-question-mark", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain('Disallow to use "!"'); + }); + + it("should detect no-hankaku-kana violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/no-hankaku-kana", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain("Disallow to use 半角カタカナ"); + }); + + it("should detect ja-no-weak-phrase violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/ja-no-weak-phrase", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain( + '弱い表現: "かも" が使われています', + ); + }); + + it("should detect ja-no-successive-word violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/ja-no-successive-word", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain("が連続して2回使われています"); + }); + + it("should detect ja-no-abusage violations", () => { + const violations = textlintResult.messages.filter( + (message) => message.ruleId === "ja-technical-writing/ja-no-abusage", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations.some((v) => v.message.includes("可変する"))).toBe( + true, + ); + expect(violations.some((v) => v.message.includes("適用"))).toBe(true); + }); + + it("should detect ja-no-redundant-expression violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === + "ja-technical-writing/ja-no-redundant-expression", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain( + 'することが可能です"は冗長な表現', + ); + }); + + it("should detect ja-unnatural-alphabet violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/ja-unnatural-alphabet", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain("不自然なアルファベット"); + }); + + it("should detect no-unmatched-pair violations", () => { + const violations = textlintResult.messages.filter( + (message) => + message.ruleId === "ja-technical-writing/no-unmatched-pair", + ); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain( + "Cannot find a pairing character for (", + ); + }); + }); + }); +}); From 2ba2503fadc412633f45f4f2aca965950d6899b2 Mon Sep 17 00:00:00 2001 From: 3w36zj6 <52315048+3w36zj6@users.noreply.github.com> Date: Sun, 1 Jun 2025 21:45:34 +0900 Subject: [PATCH 4/5] test: refactor linting tests to reduce duplication --- test/integration/linting.test.ts | 332 +++++++++++-------------------- 1 file changed, 119 insertions(+), 213 deletions(-) diff --git a/test/integration/linting.test.ts b/test/integration/linting.test.ts index 95686a7..a31f335 100644 --- a/test/integration/linting.test.ts +++ b/test/integration/linting.test.ts @@ -49,219 +49,125 @@ describe("linting", () => { ); }); - it("should detect sentence-length violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/sentence-length", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain( - "exceeds the maximum sentence length", - ); - }); - - it("should detect max-ten violations", () => { - const violations = textlintResult.messages.filter( - (message) => message.ruleId === "ja-technical-writing/max-ten", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain('一つの文で"、"を4つ以上使用'); - }); - - it("should detect max-kanji-continuous-len violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/max-kanji-continuous-len", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain("漢字が6つ以上連続"); - }); - - it("should detect arabic-kanji-numbers violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/arabic-kanji-numbers", - ); - expect(violations.length).toBeGreaterThan(0); - expect( - violations.some((v) => v.message.includes("十番目 => 10番目")), - ).toBe(true); - expect( - violations.some((v) => v.message.includes("1時的 => 一時的")), - ).toBe(true); - }); - - it("should detect no-mix-dearu-desumasu violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/no-mix-dearu-desumasu", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain( - 'である"調 と "ですます"調 が混在', - ); - }); - - it("should detect ja-no-mixed-period violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/ja-no-mixed-period", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain('文末が"。"で終わっていません'); - }); - - it("should detect no-double-negative-ja violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/no-double-negative-ja", - ); - expect(violations.length).toBeGreaterThan(0); - expect( - violations.some((v) => v.message.includes("二重否定: 〜なくもない")), - ).toBe(true); - expect( - violations.some((v) => - v.message.includes("二重否定: 〜ないことはない"), - ), - ).toBe(true); - }); - - it("should detect no-doubled-joshi violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/no-doubled-joshi", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain( - "一文に二回以上利用されている助詞", - ); - }); - - it("should detect no-dropping-the-ra violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/no-dropping-the-ra", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain("ら抜き言葉を使用"); - }); - - it("should detect no-doubled-conjunctive-particle-ga violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === - "ja-technical-writing/no-doubled-conjunctive-particle-ga", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain( - '逆接の接続助詞 "が" が二回以上使われています', - ); - }); - - it("should detect no-doubled-conjunction violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/no-doubled-conjunction", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain("同じ接続詞(しかし)が連続"); - }); - - it("should detect no-nfd violations", () => { - const violations = textlintResult.messages.filter( - (message) => message.ruleId === "ja-technical-writing/no-nfd", - ); - expect(violations.length).toBeGreaterThan(0); - expect( - violations.some((v) => v.message.includes('ホ゜" => "ポ"')), - ).toBe(true); - expect( - violations.some((v) => v.message.includes('シ゛" => "ジ"')), - ).toBe(true); - }); - - it("should detect no-exclamation-question-mark violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === - "ja-technical-writing/no-exclamation-question-mark", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain('Disallow to use "!"'); - }); - - it("should detect no-hankaku-kana violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/no-hankaku-kana", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain("Disallow to use 半角カタカナ"); - }); - - it("should detect ja-no-weak-phrase violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/ja-no-weak-phrase", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain( - '弱い表現: "かも" が使われています', - ); - }); - - it("should detect ja-no-successive-word violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/ja-no-successive-word", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain("が連続して2回使われています"); - }); - - it("should detect ja-no-abusage violations", () => { - const violations = textlintResult.messages.filter( - (message) => message.ruleId === "ja-technical-writing/ja-no-abusage", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations.some((v) => v.message.includes("可変する"))).toBe( - true, - ); - expect(violations.some((v) => v.message.includes("適用"))).toBe(true); - }); - - it("should detect ja-no-redundant-expression violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === - "ja-technical-writing/ja-no-redundant-expression", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain( - 'することが可能です"は冗長な表現', - ); - }); - - it("should detect ja-unnatural-alphabet violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/ja-unnatural-alphabet", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain("不自然なアルファベット"); - }); - - it("should detect no-unmatched-pair violations", () => { - const violations = textlintResult.messages.filter( - (message) => - message.ruleId === "ja-technical-writing/no-unmatched-pair", - ); - expect(violations.length).toBeGreaterThan(0); - expect(violations[0].message).toContain( - "Cannot find a pairing character for (", - ); - }); + // Rule test configurations + const ruleTests = [ + { + ruleId: "sentence-length", + expectedMessage: "exceeds the maximum sentence length", + }, + { + ruleId: "max-ten", + expectedMessage: '一つの文で"、"を4つ以上使用', + }, + { + ruleId: "max-kanji-continuous-len", + expectedMessage: "漢字が6つ以上連続", + }, + { + ruleId: "no-mix-dearu-desumasu", + expectedMessage: 'である"調 と "ですます"調 が混在', + }, + { + ruleId: "ja-no-mixed-period", + expectedMessage: '文末が"。"で終わっていません', + }, + { + ruleId: "no-doubled-joshi", + expectedMessage: "一文に二回以上利用されている助詞", + }, + { + ruleId: "no-dropping-the-ra", + expectedMessage: "ら抜き言葉を使用", + }, + { + ruleId: "no-doubled-conjunctive-particle-ga", + expectedMessage: '逆接の接続助詞 "が" が二回以上使われています', + }, + { + ruleId: "no-doubled-conjunction", + expectedMessage: "同じ接続詞(しかし)が連続", + }, + { + ruleId: "no-exclamation-question-mark", + expectedMessage: 'Disallow to use "!"', + }, + { + ruleId: "no-hankaku-kana", + expectedMessage: "Disallow to use 半角カタカナ", + }, + { + ruleId: "ja-no-weak-phrase", + expectedMessage: '弱い表現: "かも" が使われています', + }, + { + ruleId: "ja-no-successive-word", + expectedMessage: "が連続して2回使われています", + }, + { + ruleId: "ja-no-redundant-expression", + expectedMessage: 'することが可能です"は冗長な表現', + }, + { + ruleId: "ja-unnatural-alphabet", + expectedMessage: "不自然なアルファベット", + }, + { + ruleId: "no-unmatched-pair", + expectedMessage: "Cannot find a pairing character for (", + }, + ]; + + // Special cases with multiple expected messages + const multiMessageTests = [ + { + ruleId: "arabic-kanji-numbers", + expectedMessages: ["十番目 => 10番目", "1時的 => 一時的"], + }, + { + ruleId: "no-double-negative-ja", + expectedMessages: [ + "二重否定: 〜なくもない", + "二重否定: 〜ないことはない", + ], + }, + { + ruleId: "no-nfd", + expectedMessages: ['ホ゜" => "ポ"', 'シ゛" => "ジ"'], + }, + { + ruleId: "ja-no-abusage", + expectedMessages: ["可変する", "適用"], + }, + ]; + + const getViolations = (ruleId: string) => { + return textlintResult.messages.filter( + (message) => message.ruleId === `ja-technical-writing/${ruleId}`, + ); + }; + + // Single message tests + for (const { ruleId, expectedMessage } of ruleTests) { + it(`should detect ${ruleId} violations`, () => { + const violations = getViolations(ruleId); + expect(violations.length).toBeGreaterThan(0); + expect(violations[0].message).toContain(expectedMessage); + }); + } + + // Multi-message tests + for (const { ruleId, expectedMessages } of multiMessageTests) { + it(`should detect ${ruleId} violations`, () => { + const violations = getViolations(ruleId); + expect(violations.length).toBeGreaterThan(0); + + for (const expectedMessage of expectedMessages) { + expect( + violations.some((v) => v.message.includes(expectedMessage)), + ).toBe(true); + } + }); + } }); }); }); From 42041f7eff26062f791a5ac21d761d8fb1720a04 Mon Sep 17 00:00:00 2001 From: 3w36zj6 <52315048+3w36zj6@users.noreply.github.com> Date: Sun, 1 Jun 2025 22:01:09 +0900 Subject: [PATCH 5/5] test: use preset rules configuration --- test/integration/linting.test.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/integration/linting.test.ts b/test/integration/linting.test.ts index a31f335..fb4440d 100644 --- a/test/integration/linting.test.ts +++ b/test/integration/linting.test.ts @@ -6,7 +6,7 @@ import { type TextlintResult, } from "@textlint/kernel"; // @ts-expect-error -import { rules } from "textlint-rule-preset-ja-technical-writing"; +import { rules, rulesConfig } from "textlint-rule-preset-ja-technical-writing"; import { beforeAll, describe, expect, it } from "vitest"; @@ -42,6 +42,7 @@ describe("linting", () => { ({ ruleId: `ja-technical-writing/${id}`, rule: rule, + options: rulesConfig[id] || true, }) as TextlintKernelRule, ), ], @@ -61,11 +62,11 @@ describe("linting", () => { }, { ruleId: "max-kanji-continuous-len", - expectedMessage: "漢字が6つ以上連続", + expectedMessage: "漢字が7つ以上連続", }, { ruleId: "no-mix-dearu-desumasu", - expectedMessage: 'である"調 と "ですます"調 が混在', + expectedMessage: '"ですます"調 でなければなりません', }, { ruleId: "ja-no-mixed-period",