@markuplint/create-rule 4.7.22 → 4.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,194 @@
1
+ # @markuplint/create-rule
2
+
3
+ ## 概要
4
+
5
+ `@markuplint/create-rule` は markuplint ルールのスキャフォルディング CLI です。対話型ウィザードでユーザーからパラメータを収集し、3つのスキャフォルド戦略のいずれかにディスパッチして、ルール開発に必要なボイラープレートファイルを生成します。また、非対話的に使用するためのプログラマティック API(`createRuleHelper()`)も公開しています。
6
+
7
+ ## ディレクトリ構成
8
+
9
+ ```
10
+ src/
11
+ ├── cli.ts — 対話型 CLI ウィザード(bin のエントリポイント)
12
+ ├── types.ts — 型定義(Purpose, Params, Result, File)
13
+ ├── create-rule-helper.ts — 目的ベースルーター(戦略にディスパッチ)
14
+ ├── create-rule-to-project.ts — 戦略: 現在のプロジェクトにルールを追加
15
+ ├── create-rule-package.ts — 戦略: スタンドアロン npm パッケージを作成
16
+ ├── create-rule-to-core.ts — 戦略: コアルールに貢献
17
+ ├── install-scaffold.ts — 低レベルスキャフォルドインストーラー
18
+ ├── transfer.ts — テンプレートの転送、置換、トランスパイル、フォーマット
19
+ ├── is-markuplint-repo.ts — cwd が markuplint モノレポ内かを検出
20
+ ├── search-core-repository.ts — モノレポルートを上方向に検索
21
+ ├── read-package-json.ts — package.json の読み取りとパース
22
+ ├── fs-exists.ts — ファイル存在チェックユーティリティ
23
+ ├── glob.ts — Glob ラッパー
24
+ └── create-rule-helper-error.ts — カスタムエラークラス
25
+ bin/
26
+ └── create-rule.mjs — Node.js 実行ファイル(cli.ts を呼び出す)
27
+ scaffold/
28
+ ├── core/ — コアルール貢献用テンプレート
29
+ │ ├── index.ts — ルール実装テンプレート
30
+ │ ├── index.spec.ts — テストテンプレート
31
+ │ ├── meta.ts — ルールメタデータテンプレート
32
+ │ ├── schema.json — JSON Schema テンプレート
33
+ │ ├── README.md — 英語ドキュメントテンプレート
34
+ │ └── README.ja.md — 日本語ドキュメントテンプレート
35
+ ├── project/ — プロジェクトローカルプラグイン用テンプレート
36
+ │ ├── index.ts — プラグインエントリポイントテンプレート
37
+ │ └── rules/
38
+ │ ├── __ruleName__.ts — ルール実装テンプレート
39
+ │ └── __ruleName__.spec.ts — テストテンプレート
40
+ └── package/ — 公開パッケージ用テンプレート
41
+ ├── README.md — パッケージ README テンプレート
42
+ ├── tsconfig.json — TypeScript 設定テンプレート
43
+ └── src/
44
+ ├── index.ts — プラグインエントリポイントテンプレート
45
+ └── rules/
46
+ └── __ruleName__.ts — ルール実装テンプレート
47
+ ```
48
+
49
+ ## アーキテクチャ図
50
+
51
+ ```mermaid
52
+ flowchart TD
53
+ subgraph cli ["CLI レイヤー"]
54
+ bin["bin/create-rule.mjs"]
55
+ wizard["cli.ts\n対話型ウィザード"]
56
+ end
57
+
58
+ subgraph router ["ルーター"]
59
+ helper["create-rule-helper.ts\ncreateRuleHelper()"]
60
+ end
61
+
62
+ subgraph strategies ["スキャフォルド戦略"]
63
+ project["create-rule-to-project.ts\nプロジェクトに追加"]
64
+ package["create-rule-package.ts\nパッケージとして公開"]
65
+ core["create-rule-to-core.ts\nコアに貢献"]
66
+ end
67
+
68
+ subgraph engine ["スキャフォルドエンジン"]
69
+ install["install-scaffold.ts\ninstallScaffold()"]
70
+ transfer["transfer.ts\ntransfer()"]
71
+ end
72
+
73
+ subgraph templates ["テンプレート"]
74
+ tplProject["scaffold/project/"]
75
+ tplPackage["scaffold/package/"]
76
+ tplCore["scaffold/core/"]
77
+ end
78
+
79
+ bin --> wizard
80
+ wizard -->|"params"| helper
81
+ helper -->|"ADD_TO_PROJECT"| project
82
+ helper -->|"PUBLISH_AS_PACKAGE"| package
83
+ helper -->|"CONTRIBUTE_TO_CORE"| core
84
+ project --> install
85
+ package --> install
86
+ core --> install
87
+ install --> transfer
88
+ transfer -->|"read"| tplProject
89
+ transfer -->|"read"| tplPackage
90
+ transfer -->|"read"| tplCore
91
+ ```
92
+
93
+ ## CLI フロー
94
+
95
+ CLI バイナリ(`bin/create-rule.mjs`)は `cli.ts` の `createRule()` を呼び出し、`@markuplint/cli-utils` を使用して対話型の質問シーケンスを実行します:
96
+
97
+ 1. **目的の選択** — `ADD_TO_PROJECT`、`PUBLISH_AS_PACKAGE`、`CONTRIBUTE_TO_CORE` のいずれか(コアオプションは markuplint モノレポ内でのみ表示)
98
+ 2. **プラグイン/ディレクトリ名** — ケバブケースの識別子(コアの場合はスキップ)
99
+ 3. **ルール名** — ケバブケースの識別子
100
+ 4. **コア固有の質問** — 説明、カテゴリ、重大度(`CONTRIBUTE_TO_CORE` の場合のみ)
101
+ 5. **言語** — TypeScript または JavaScript(コアは常に TypeScript)
102
+ 6. **テスト生成** — 真偽値(コアは常にテストを含む)
103
+
104
+ 収集されたパラメータは `createRuleHelper()` に渡され、適切な戦略にルーティングされます。
105
+
106
+ ## スキャフォルド戦略
107
+
108
+ ### `createRuleToProject()`
109
+
110
+ `<cwd>/<pluginName>/` にプラグインディレクトリを作成します。ディレクトリが既に存在する場合は失敗します。`scaffold/project/` テンプレートを使用します。
111
+
112
+ ### `createRulePackage()`
113
+
114
+ 現在の作業ディレクトリにスキャフォルドします。ディレクトリが空である必要があります。`scaffold/package/` テンプレートを使用し、ビルド/テストスクリプトと依存関係の宣言を含む `package.json` を追加で生成します。
115
+
116
+ ### `createRuleToCore()`
117
+
118
+ markuplint モノレポ内の `packages/@markuplint/rules/src/<ruleName>/` にルールディレクトリを作成します。`searchCoreRepository()` で cwd から上方向にリポジトリルートを検索します。ルールディレクトリが既に存在する場合、またはモノレポルートが見つからない場合は失敗します。TypeScript とテストが常に有効な状態で `scaffold/core/` テンプレートを使用します。
119
+
120
+ ## テンプレートシステム
121
+
122
+ スキャフォルドエンジンは3つのステージでテンプレートファイルを処理します:
123
+
124
+ ### 1. プレースホルダー置換
125
+
126
+ テンプレートファイルにはダブルアンダースコアのプレースホルダーが含まれ、ユーザー指定の値に置換されます:
127
+
128
+ | プレースホルダー | 置換内容 | 例 |
129
+ | ----------------- | ------------------------------ | ------------------------------- |
130
+ | `__pluginName__` | プラグイン名(そのまま) | `my-plugin` |
131
+ | `__pluginName__c` | プラグイン名(キャメルケース) | `myPlugin` |
132
+ | `__ruleName__` | ルール名(そのまま) | `no-empty-alt` |
133
+ | `__ruleName__c` | ルール名(キャメルケース) | `noEmptyAlt` |
134
+ | `__description__` | ルールの説明(コアのみ) | `Disallow empty alt attributes` |
135
+ | `__category__` | ルールカテゴリ(コアのみ) | `validation` |
136
+ | `__severity__` | デフォルト重大度(コアのみ) | `error` |
137
+
138
+ `__<name>__c` サフィックスはキャメルケース変換をトリガーします。ハイフンが除去され、次の文字が大文字化されます(例: `my-rule` → `myRule`)。
139
+
140
+ `__ruleName__` を含むファイル名も実際のルール名にリネームされます。
141
+
142
+ ### 2. TypeScript から JavaScript へのトランスパイル(オプション)
143
+
144
+ ユーザーが JavaScript を選択した場合、`.ts` ファイルは TypeScript コンパイラ API(`tsc.transpile()`)を使用して ESNext ターゲットでトランスパイルされます。生成された `.js` ファイルでは、可読性のためにコメントと `export` キーワードの前に空行が挿入されます。
145
+
146
+ ### 3. Prettier フォーマット
147
+
148
+ すべての出力ファイルは Prettier でフォーマットされます。テンプレート内の `// prettier-ignore` コメントはフォーマット前に自動的に削除されます。
149
+
150
+ ## スキャフォルドテンプレート
151
+
152
+ ### コアテンプレート(`scaffold/core/`)
153
+
154
+ | テンプレート | 生成ファイル | 内容 |
155
+ | --------------- | --------------- | ----------------------------------------------------- |
156
+ | `index.ts` | `index.ts` | Element/Attr ウォーカーを使った `createRule()` ルール |
157
+ | `index.spec.ts` | `index.spec.ts` | markuplint の `mlRuleTest()` を使ったテスト |
158
+ | `meta.ts` | `meta.ts` | ルールメタデータ(カテゴリ) |
159
+ | `schema.json` | `schema.json` | ルール値/オプションの JSON Schema |
160
+ | `README.md` | `README.md` | 例付き英語ドキュメント |
161
+ | `README.ja.md` | `README.ja.md` | 例付き日本語ドキュメント |
162
+
163
+ ### プロジェクトテンプレート(`scaffold/project/`)
164
+
165
+ | テンプレート | 生成ファイル | 内容 |
166
+ | ---------------------------- | -------------------------- | ------------------------------------------- |
167
+ | `index.ts` | `index.ts` | `createPlugin()` を使ったプラグインエントリ |
168
+ | `rules/__ruleName__.ts` | `rules/<ruleName>.ts` | コメントチェックの例を含むルール |
169
+ | `rules/__ruleName__.spec.ts` | `rules/<ruleName>.spec.ts` | 期待される違反アサーション付きテスト |
170
+
171
+ ### パッケージテンプレート(`scaffold/package/`)
172
+
173
+ | テンプレート | 生成ファイル | 内容 |
174
+ | --------------------------- | ------------------------- | ------------------------------------------- |
175
+ | `README.md` | `README.md` | インストール/設定付きパッケージドキュメント |
176
+ | `tsconfig.json` | `tsconfig.json` | TypeScript 設定 |
177
+ | `src/index.ts` | `src/index.ts` | `createPlugin()` を使ったプラグインエントリ |
178
+ | `src/rules/__ruleName__.ts` | `src/rules/<ruleName>.ts` | コメントチェックの例を含むルール |
179
+
180
+ 加えて、`installScaffold()` は適切なスクリプトと依存関係を含む `package.json` をプログラム的に(テンプレートからではなく)生成します。
181
+
182
+ ## 主要ソースファイル
183
+
184
+ | ファイル | 役割 |
185
+ | ------------------------------- | ----------------------------------------------------------------------------- |
186
+ | `bin/create-rule.mjs` | CLI 実行ファイルエントリポイント |
187
+ | `src/cli.ts` | 対話型質問ウィザード |
188
+ | `src/types.ts` | 型定義(`CreateRulePurpose`、`CreateRuleHelperParams`、`File`) |
189
+ | `src/create-rule-helper.ts` | スキャフォルド戦略にディスパッチする目的ベースルーター |
190
+ | `src/create-rule-to-project.ts` | プロジェクトローカルプラグインのスキャフォルド戦略 |
191
+ | `src/create-rule-package.ts` | 公開可能な npm パッケージのスキャフォルド戦略 |
192
+ | `src/create-rule-to-core.ts` | コアルール貢献のスキャフォルド戦略 |
193
+ | `src/install-scaffold.ts` | 低レベルスキャフォルドインストーラー(テンプレートコピー、package.json 生成) |
194
+ | `src/transfer.ts` | テンプレート処理(置換、トランスパイル、Prettier フォーマット) |
@@ -0,0 +1,194 @@
1
+ # @markuplint/create-rule
2
+
3
+ ## Overview
4
+
5
+ `@markuplint/create-rule` is the scaffolding CLI for markuplint rules. It provides an interactive wizard that collects parameters from the user and dispatches to one of three scaffold strategies, each generating the boilerplate files needed for rule development. The package also exposes a programmatic API (`createRuleHelper()`) for non-interactive use.
6
+
7
+ ## Directory Structure
8
+
9
+ ```
10
+ src/
11
+ ├── cli.ts — Interactive CLI wizard (entry point for bin)
12
+ ├── types.ts — Type definitions (Purpose, Params, Result, File)
13
+ ├── create-rule-helper.ts — Purpose-based router (dispatches to strategies)
14
+ ├── create-rule-to-project.ts — Strategy: add rule to current project
15
+ ├── create-rule-package.ts — Strategy: create standalone npm package
16
+ ├── create-rule-to-core.ts — Strategy: contribute to core rules
17
+ ├── install-scaffold.ts — Low-level scaffold installer
18
+ ├── transfer.ts — Template transfer, replacement, transpile, format
19
+ ├── is-markuplint-repo.ts — Detects if cwd is inside the markuplint monorepo
20
+ ├── search-core-repository.ts — Searches upward for the monorepo root
21
+ ├── read-package-json.ts — Reads and parses package.json
22
+ ├── fs-exists.ts — File existence check utility
23
+ ├── glob.ts — Glob wrapper
24
+ └── create-rule-helper-error.ts — Custom error class
25
+ bin/
26
+ └── create-rule.mjs — Node.js executable (calls cli.ts)
27
+ scaffold/
28
+ ├── core/ — Templates for core rule contribution
29
+ │ ├── index.ts — Rule implementation template
30
+ │ ├── index.spec.ts — Test template
31
+ │ ├── meta.ts — Rule metadata template
32
+ │ ├── schema.json — JSON Schema template
33
+ │ ├── README.md — English docs template
34
+ │ └── README.ja.md — Japanese docs template
35
+ ├── project/ — Templates for project-local plugin
36
+ │ ├── index.ts — Plugin entry point template
37
+ │ └── rules/
38
+ │ ├── __ruleName__.ts — Rule implementation template
39
+ │ └── __ruleName__.spec.ts — Test template
40
+ └── package/ — Templates for publishable package
41
+ ├── README.md — Package README template
42
+ ├── tsconfig.json — TypeScript config template
43
+ └── src/
44
+ ├── index.ts — Plugin entry point template
45
+ └── rules/
46
+ └── __ruleName__.ts — Rule implementation template
47
+ ```
48
+
49
+ ## Architecture Diagram
50
+
51
+ ```mermaid
52
+ flowchart TD
53
+ subgraph cli ["CLI Layer"]
54
+ bin["bin/create-rule.mjs"]
55
+ wizard["cli.ts\nInteractive wizard"]
56
+ end
57
+
58
+ subgraph router ["Router"]
59
+ helper["create-rule-helper.ts\ncreateRuleHelper()"]
60
+ end
61
+
62
+ subgraph strategies ["Scaffold Strategies"]
63
+ project["create-rule-to-project.ts\nAdd to project"]
64
+ package["create-rule-package.ts\nPublish as package"]
65
+ core["create-rule-to-core.ts\nContribute to core"]
66
+ end
67
+
68
+ subgraph engine ["Scaffold Engine"]
69
+ install["install-scaffold.ts\ninstallScaffold()"]
70
+ transfer["transfer.ts\ntransfer()"]
71
+ end
72
+
73
+ subgraph templates ["Templates"]
74
+ tplProject["scaffold/project/"]
75
+ tplPackage["scaffold/package/"]
76
+ tplCore["scaffold/core/"]
77
+ end
78
+
79
+ bin --> wizard
80
+ wizard -->|"params"| helper
81
+ helper -->|"ADD_TO_PROJECT"| project
82
+ helper -->|"PUBLISH_AS_PACKAGE"| package
83
+ helper -->|"CONTRIBUTE_TO_CORE"| core
84
+ project --> install
85
+ package --> install
86
+ core --> install
87
+ install --> transfer
88
+ transfer -->|"read"| tplProject
89
+ transfer -->|"read"| tplPackage
90
+ transfer -->|"read"| tplCore
91
+ ```
92
+
93
+ ## CLI Flow
94
+
95
+ The CLI binary (`bin/create-rule.mjs`) calls `createRule()` from `cli.ts`, which runs an interactive question sequence using `@markuplint/cli-utils`:
96
+
97
+ 1. **Purpose selection** — One of: `ADD_TO_PROJECT`, `PUBLISH_AS_PACKAGE`, `CONTRIBUTE_TO_CORE` (core option only appears inside the markuplint monorepo)
98
+ 2. **Plugin/directory name** — Kebab-case identifier (skipped for core)
99
+ 3. **Rule name** — Kebab-case identifier
100
+ 4. **Core-specific questions** — Description, category, severity (only for `CONTRIBUTE_TO_CORE`)
101
+ 5. **Language** — TypeScript or JavaScript (core always uses TypeScript)
102
+ 6. **Test generation** — Boolean (core always includes tests)
103
+
104
+ The collected parameters are passed to `createRuleHelper()`, which routes to the appropriate strategy.
105
+
106
+ ## Scaffold Strategies
107
+
108
+ ### `createRuleToProject()`
109
+
110
+ Creates a plugin directory at `<cwd>/<pluginName>/`. Fails if the directory already exists. Uses the `scaffold/project/` templates.
111
+
112
+ ### `createRulePackage()`
113
+
114
+ Scaffolds in the current working directory. Requires the directory to be empty. Uses the `scaffold/package/` templates and generates an additional `package.json` with build/test scripts and dependency declarations.
115
+
116
+ ### `createRuleToCore()`
117
+
118
+ Creates a rule directory at `packages/@markuplint/rules/src/<ruleName>/` within the markuplint monorepo. Searches upward from the cwd to find the repository root via `searchCoreRepository()`. Fails if the rule directory already exists or if the monorepo root is not found. Uses the `scaffold/core/` templates with TypeScript and tests always enabled.
119
+
120
+ ## Template System
121
+
122
+ The scaffold engine processes template files through three stages:
123
+
124
+ ### 1. Placeholder Replacement
125
+
126
+ Template files contain double-underscore placeholders that are replaced with user-provided values:
127
+
128
+ | Placeholder | Replaced with | Example |
129
+ | ----------------- | ---------------------------- | ------------------------------- |
130
+ | `__pluginName__` | Plugin name (as-is) | `my-plugin` |
131
+ | `__pluginName__c` | Plugin name (camelCase) | `myPlugin` |
132
+ | `__ruleName__` | Rule name (as-is) | `no-empty-alt` |
133
+ | `__ruleName__c` | Rule name (camelCase) | `noEmptyAlt` |
134
+ | `__description__` | Rule description (core only) | `Disallow empty alt attributes` |
135
+ | `__category__` | Rule category (core only) | `validation` |
136
+ | `__severity__` | Default severity (core only) | `error` |
137
+
138
+ The `__<name>__c` suffix triggers camelCase conversion: hyphens are removed and the following letter is uppercased (e.g., `my-rule` becomes `myRule`).
139
+
140
+ File names containing `__ruleName__` are also renamed to the actual rule name.
141
+
142
+ ### 2. TypeScript-to-JavaScript Transpilation (optional)
143
+
144
+ When the user selects JavaScript, `.ts` files are transpiled using the TypeScript compiler API (`tsc.transpile()`) targeting ESNext. The resulting `.js` files have blank lines inserted before comments and `export` keywords for readability.
145
+
146
+ ### 3. Prettier Formatting
147
+
148
+ All output files are formatted with Prettier. Any `// prettier-ignore` comments in templates are automatically stripped before formatting.
149
+
150
+ ## Scaffold Templates
151
+
152
+ ### Core templates (`scaffold/core/`)
153
+
154
+ | Template | Generated file | Content |
155
+ | --------------- | --------------- | --------------------------------------------------- |
156
+ | `index.ts` | `index.ts` | Rule using `createRule()` with Element/Attr walkers |
157
+ | `index.spec.ts` | `index.spec.ts` | Test using `mlRuleTest()` from markuplint |
158
+ | `meta.ts` | `meta.ts` | Rule metadata (category) |
159
+ | `schema.json` | `schema.json` | JSON Schema for rule value/options |
160
+ | `README.md` | `README.md` | English documentation with examples |
161
+ | `README.ja.md` | `README.ja.md` | Japanese documentation with examples |
162
+
163
+ ### Project templates (`scaffold/project/`)
164
+
165
+ | Template | Generated file | Content |
166
+ | ---------------------------- | -------------------------- | --------------------------------------- |
167
+ | `index.ts` | `index.ts` | Plugin entry using `createPlugin()` |
168
+ | `rules/__ruleName__.ts` | `rules/<ruleName>.ts` | Rule with comment-checking example |
169
+ | `rules/__ruleName__.spec.ts` | `rules/<ruleName>.spec.ts` | Test with expected violation assertions |
170
+
171
+ ### Package templates (`scaffold/package/`)
172
+
173
+ | Template | Generated file | Content |
174
+ | --------------------------- | ------------------------- | ----------------------------------------- |
175
+ | `README.md` | `README.md` | Package documentation with install/config |
176
+ | `tsconfig.json` | `tsconfig.json` | TypeScript configuration |
177
+ | `src/index.ts` | `src/index.ts` | Plugin entry using `createPlugin()` |
178
+ | `src/rules/__ruleName__.ts` | `src/rules/<ruleName>.ts` | Rule with comment-checking example |
179
+
180
+ Additionally, `installScaffold()` generates a `package.json` programmatically (not from a template) with appropriate scripts and dependencies.
181
+
182
+ ## Key Source Files
183
+
184
+ | File | Role |
185
+ | ------------------------------- | ------------------------------------------------------------------------ |
186
+ | `bin/create-rule.mjs` | CLI executable entry point |
187
+ | `src/cli.ts` | Interactive question wizard |
188
+ | `src/types.ts` | Type definitions (`CreateRulePurpose`, `CreateRuleHelperParams`, `File`) |
189
+ | `src/create-rule-helper.ts` | Purpose-based router dispatching to scaffold strategies |
190
+ | `src/create-rule-to-project.ts` | Scaffold strategy for project-local plugins |
191
+ | `src/create-rule-package.ts` | Scaffold strategy for publishable npm packages |
192
+ | `src/create-rule-to-core.ts` | Scaffold strategy for core rule contributions |
193
+ | `src/install-scaffold.ts` | Low-level scaffold installer (copies templates, generates package.json) |
194
+ | `src/transfer.ts` | Template processing (replacement, transpile, Prettier format) |
package/CHANGELOG.md CHANGED
@@ -3,13 +3,23 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [4.7.22](https://github.com/markuplint/markuplint/compare/@markuplint/create-rule@4.7.21...@markuplint/create-rule@4.7.22) (2025-11-05)
6
+ # [4.18.0](https://github.com/markuplint/markuplint/compare/v4.14.1...v4.18.0) (2026-04-22)
7
+
8
+ **Note:** Version bump only for package @markuplint/create-rule
9
+
10
+ ## [4.8.1](https://github.com/markuplint/markuplint/compare/@markuplint/create-rule@4.8.0...@markuplint/create-rule@4.8.1) (2026-04-21)
7
11
 
8
12
  **Note:** Version bump only for package @markuplint/create-rule
9
13
 
14
+ # [4.8.0](https://github.com/markuplint/markuplint/compare/@markuplint/create-rule@4.7.22...@markuplint/create-rule@4.8.0) (2026-02-10)
10
15
 
16
+ ### Features
11
17
 
18
+ - **create-rule:** add non-interactive CLI mode for AI/automation usage ([33443c6](https://github.com/markuplint/markuplint/commit/33443c63c508023b560f5386580ecdb40bf1fae2))
12
19
 
20
+ ## [4.7.22](https://github.com/markuplint/markuplint/compare/@markuplint/create-rule@4.7.21...@markuplint/create-rule@4.7.22) (2025-11-05)
21
+
22
+ **Note:** Version bump only for package @markuplint/create-rule
13
23
 
14
24
  ## [4.7.21](https://github.com/markuplint/markuplint/compare/@markuplint/create-rule@4.7.20...@markuplint/create-rule@4.7.21) (2025-08-24)
15
25
 
package/README.md CHANGED
@@ -2,8 +2,133 @@
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/%40markuplint%2Fcreate-rule.svg)](https://www.npmjs.com/package/@markuplint/create-rule)
4
4
 
5
+ ## Overview
6
+
7
+ A CLI scaffolding tool for creating new markuplint rules. It provides both an interactive wizard and a non-interactive CLI mode that generates all the boilerplate files needed for rule development, including source files, tests, and configuration.
8
+
5
9
  ## Usage
6
10
 
11
+ ### Interactive mode
12
+
13
+ Run without arguments to start the guided wizard:
14
+
7
15
  ```shell
8
16
  $ npx @markuplint/create-rule
9
17
  ```
18
+
19
+ ### Non-interactive mode
20
+
21
+ Pass CLI options to create a rule in a single command:
22
+
23
+ ```shell
24
+ # Add a rule to this project
25
+ $ npx @markuplint/create-rule -p project -n my-plugin -r no-empty-alt
26
+
27
+ # Create a publishable package (JavaScript, no tests)
28
+ $ npx @markuplint/create-rule -p package -n my-plugin -r no-empty-alt -l js --no-test
29
+
30
+ # Contribute to core
31
+ $ npx @markuplint/create-rule -p core -r no-empty-alt -d "Disallow empty alt" -c a11y -s error
32
+
33
+ # JSON output (useful for scripting and AI tooling)
34
+ $ npx @markuplint/create-rule -p project -n my-plugin -r no-empty-alt --json
35
+ ```
36
+
37
+ ### Options
38
+
39
+ | Option | Short | Description | Default |
40
+ | ---------------------- | ----- | ---------------------------------------- | -------------------------------- |
41
+ | `--purpose <type>` | `-p` | Purpose: `project`, `package`, or `core` | _(required)_ |
42
+ | `--plugin-name <name>` | `-n` | Plugin/directory name in kebab-case | _(required for project/package)_ |
43
+ | `--rule-name <name>` | `-r` | Rule name in kebab-case | _(required)_ |
44
+ | `--lang <lang>` | `-l` | Language: `ts` or `js` | `ts` |
45
+ | `--test` | `-t` | Generate test files | `true` |
46
+ | `--no-test` | | Skip test file generation | |
47
+ | `--description <text>` | `-d` | Rule description | _(required for core)_ |
48
+ | `--category <cat>` | `-c` | Category (see below) | _(required for core)_ |
49
+ | `--severity <level>` | `-s` | Severity: `error` or `warning` | _(required for core)_ |
50
+ | `--json` | | Output result as JSON | `false` |
51
+ | `--help` | `-h` | Show help message | |
52
+
53
+ Available categories: `validation`, `a11y`, `naming-convention`, `maintainability`, `style`
54
+
55
+ > When contributing to core (`--purpose core`), `--lang` is always TypeScript and `--test` is always enabled regardless of the options provided.
56
+
57
+ ## Modes
58
+
59
+ The CLI supports three scaffolding modes depending on your goal:
60
+
61
+ | Mode | Description | When to use |
62
+ | ---------------------- | ------------------------------------------------------------- | ------------------------------------------------- |
63
+ | **Add to project** | Creates a local plugin directory in your project | Adding a custom rule to an existing project |
64
+ | **Publish as package** | Scaffolds a standalone npm package with `package.json` | Distributing a rule as an installable npm package |
65
+ | **Contribute to core** | Adds a rule to `@markuplint/rules` (only inside the monorepo) | Contributing a new built-in rule to markuplint |
66
+
67
+ ## Interactive Flow
68
+
69
+ The CLI asks questions in the following order:
70
+
71
+ 1. **Purpose** — Select one of the three modes above
72
+ 2. **Directory / plugin name** — The directory name (for project mode) or plugin name (for package mode); skipped for core mode
73
+ 3. **Rule name** — The kebab-case name of the rule (e.g., `no-empty-alt`)
74
+ 4. **Core-only questions** (contribute to core only):
75
+ - Description
76
+ - Category (`validation`, `a11y`, `naming-convention`, `maintainability`, `style`)
77
+ - Severity (`error` or `warning`)
78
+ 5. **Language** — TypeScript or JavaScript (core mode always uses TypeScript)
79
+ 6. **Tests** — Whether to generate test files (core mode always includes tests)
80
+
81
+ ## Generated Files
82
+
83
+ ### Add to project
84
+
85
+ ```
86
+ <pluginName>/
87
+ ├── index.ts (or .js) — Plugin entry point
88
+ └── rules/
89
+ ├── <ruleName>.ts (or .js) — Rule implementation
90
+ └── <ruleName>.spec.ts (or .js) — Test file (if selected)
91
+ ```
92
+
93
+ ### Publish as package
94
+
95
+ ```
96
+ <cwd>/
97
+ ├── package.json — Package manifest with scripts
98
+ ├── tsconfig.json — TypeScript config (if TypeScript)
99
+ ├── README.md — Package README
100
+ └── src/
101
+ ├── index.ts (or .js) — Plugin entry point
102
+ └── rules/
103
+ └── <ruleName>.ts (or .js) — Rule implementation
104
+ ```
105
+
106
+ ### Contribute to core
107
+
108
+ ```
109
+ packages/@markuplint/rules/src/<ruleName>/
110
+ ├── index.ts — Rule implementation
111
+ ├── index.spec.ts — Test file
112
+ ├── meta.ts — Rule metadata
113
+ ├── schema.json — Value/options JSON Schema
114
+ ├── README.md — English documentation
115
+ └── README.ja.md — Japanese documentation
116
+ ```
117
+
118
+ ## Programmatic API
119
+
120
+ The scaffolding logic can be used programmatically:
121
+
122
+ ```typescript
123
+ import { createRuleHelper } from '@markuplint/create-rule';
124
+
125
+ const result = await createRuleHelper({
126
+ purpose: 'ADD_TO_PROJECT',
127
+ pluginName: 'my-plugin',
128
+ ruleName: 'no-empty-alt',
129
+ lang: 'TYPESCRIPT',
130
+ needTest: true,
131
+ });
132
+ ```
133
+
134
+ See [`src/types.ts`](src/types.ts) for the full type definitions of `CreateRuleHelperParams` and `CreateRuleHelperResult`.
package/SKILL.md ADDED
@@ -0,0 +1,74 @@
1
+ ---
2
+ description: Maintenance tasks for @markuplint/create-rule — CLI scaffolding tool for markuplint rules
3
+ globs:
4
+ - packages/@markuplint/create-rule/src/**/*.ts
5
+ - packages/@markuplint/create-rule/scaffold/**/*
6
+ - packages/@markuplint/create-rule/bin/*.mjs
7
+ alwaysApply: false
8
+ ---
9
+
10
+ # @markuplint/create-rule Maintenance
11
+
12
+ You are maintaining `@markuplint/create-rule`, the CLI scaffolding tool for creating new markuplint rules.
13
+
14
+ ## Architecture
15
+
16
+ See [ARCHITECTURE.md](ARCHITECTURE.md) for the full architecture documentation including the scaffold engine, template system, and strategy patterns.
17
+
18
+ For detailed maintenance procedures, see [docs/maintenance.md](docs/maintenance.md) ([Japanese](docs/maintenance.ja.md)).
19
+
20
+ ## Key Files
21
+
22
+ | File | Role |
23
+ | ------------------------------- | -------------------------------------------------------------- |
24
+ | `src/cli.ts` | Interactive CLI wizard (question sequence) |
25
+ | `src/types.ts` | Type definitions (`CreateRulePurpose`, params, result, `File`) |
26
+ | `src/create-rule-helper.ts` | Purpose-based router dispatching to scaffold strategies |
27
+ | `src/create-rule-to-project.ts` | Strategy: add rule to current project |
28
+ | `src/create-rule-package.ts` | Strategy: create standalone npm package |
29
+ | `src/create-rule-to-core.ts` | Strategy: contribute to core rules |
30
+ | `src/install-scaffold.ts` | Low-level scaffold installer |
31
+ | `src/transfer.ts` | Template processing (replacement, transpile, format) |
32
+ | `scaffold/core/` | Templates for core rule contributions |
33
+ | `scaffold/project/` | Templates for project-local plugins |
34
+ | `scaffold/package/` | Templates for publishable packages |
35
+
36
+ ## Tasks
37
+
38
+ ### update-scaffold-template
39
+
40
+ Update or modify scaffold template files.
41
+
42
+ 1. Edit the template files in `scaffold/{core,project,package}/`
43
+ 2. Maintain placeholder conventions:
44
+ - `__pluginName__` / `__pluginName__c` (camelCase variant)
45
+ - `__ruleName__` / `__ruleName__c` (camelCase variant)
46
+ - `__description__`, `__category__`, `__severity__` (core templates only)
47
+ - File names with `__ruleName__` are renamed to the actual rule name
48
+ 3. Note: `// prettier-ignore` comments are automatically stripped during transfer
49
+ 4. If using TypeScript, the template must also produce valid JavaScript when transpiled (for JavaScript mode)
50
+ 5. Test: `yarn test --scope @markuplint/create-rule`
51
+ 6. Build: `yarn build --scope @markuplint/create-rule`
52
+
53
+ ### add-cli-question
54
+
55
+ Add or change a question in the interactive CLI wizard.
56
+
57
+ 1. Edit the question sequence in `src/cli.ts`
58
+ 2. Add any new types to `src/types.ts` (e.g., new fields on `CreateRuleCreatorParams`)
59
+ 3. Pass the new parameter through `createRuleHelper()` in `src/create-rule-helper.ts`
60
+ 4. Update the relevant strategy functions to use the new parameter
61
+ 5. Test: `yarn test --scope @markuplint/create-rule`
62
+ 6. Build: `yarn build --scope @markuplint/create-rule`
63
+
64
+ ### add-scaffold-strategy
65
+
66
+ Add a new scaffold strategy (a fourth mode).
67
+
68
+ 1. Add a new value to `CreateRulePurpose` in `src/types.ts`
69
+ 2. Add the new choice to the selection list in `src/cli.ts`
70
+ 3. Create a new strategy file `src/create-rule-<purpose>.ts` following the pattern of existing strategies
71
+ 4. Add a new `case` branch in `src/create-rule-helper.ts`
72
+ 5. Create template files in `scaffold/<type>/` with appropriate placeholders
73
+ 6. Test: `yarn test --scope @markuplint/create-rule`
74
+ 7. Build: `yarn build --scope @markuplint/create-rule`