astro-dev-mcp 0.3.0 → 0.5.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.
package/README.md CHANGED
@@ -10,9 +10,22 @@
10
10
 
11
11
  - ✅ **コンポーネント生成**: Props定義から再利用可能なAstroコンポーネントを生成
12
12
  - ✅ **セクション生成**: コンテンツデータから`_parts`配下のセクションを生成
13
+ - **NEW**: SCSS自動生成(astro-dev mixinに準拠)
14
+ - **NEW**: app.js自動更新(Tab/Accordion等のスクリプト登録)
13
15
  - ✅ **ページ生成**: ページ構造全体を一括生成
14
16
  - ✅ **スキーマ生成**: Excel/Markdown/JSONからTypeScript型定義を自動生成
15
17
 
18
+ ### v0.2.0の主な改善点
19
+
20
+ **astro-devプロジェクトでの実際の使用経験から、以下の課題を解決しました:**
21
+
22
+ 1. ✅ **既存スクリプトの活用**: Tab.ts、Accordion.ts等のastro-dev既存スクリプトを使用
23
+ 2. ✅ **Mixinの使用**: `@include mq()`、`@include hover()`を使用したSCSS生成
24
+ 3. ✅ **.contentInner二重設定の防止**: 柔軟なコンテナ制御
25
+ 4. ✅ **スタイル分離**: Astroファイルではなく、SCSSファイルに分離
26
+
27
+ 詳細は [IMPROVEMENTS.md](./IMPROVEMENTS.md) を参照してください。
28
+
16
29
  ## インストール
17
30
 
18
31
  ### 方法1: npxで直接実行(推奨)
@@ -134,21 +147,12 @@ Props:
134
147
 
135
148
  ---
136
149
 
137
- ### 2. セクション生成
150
+ ### 2. セクション生成(改善版)
138
151
 
139
152
  **プロンプト例**:
140
153
 
141
154
  ```
142
- sampleページ用のarticlesセクションを生成してください。
143
-
144
- コンテンツ:
145
- - タイトル: 最新記事
146
- - 記事数: 4件
147
- - 各記事にタイトル、説明文、投稿日、カテゴリ、画像が必要
148
-
149
- 使用コンポーネント:
150
- - Picture
151
- - SetTime
155
+ recruitページでQ&Aをアコーディオンで実装してください。
152
156
  ```
153
157
 
154
158
  **実行されるMCPツール**:
@@ -157,20 +161,38 @@ sampleページ用のarticlesセクションを生成してください。
157
161
  {
158
162
  "name": "generate-section",
159
163
  "arguments": {
160
- "sectionType": "articles",
161
- "pageName": "sample",
164
+ "prompt": "Q&Aをアコーディオンで実装",
165
+ "pageName": "recruit",
162
166
  "content": {
163
- "ttl": "最新記事",
164
- "items": []
167
+ "ttl": "よくある質問",
168
+ "items": [
169
+ { "ttl": "質問1", "content": "回答1" },
170
+ { "ttl": "質問2", "content": "回答2" }
171
+ ]
165
172
  },
166
- "components": ["Picture", "SetTime"]
173
+ "generateScss": true,
174
+ "scssOptions": {
175
+ "spacing": {
176
+ "sectionPadding": "6rem 0",
177
+ "itemGap": "1.6rem"
178
+ }
179
+ }
167
180
  }
168
181
  }
169
182
  ```
170
183
 
171
184
  **出力**:
172
185
 
173
- - `src/pages/_parts/_sample/_articles.astro`
186
+ - `src/pages/_parts/_recruit/_qa.astro` (Astroコンポーネント)
187
+ - SCSSコード(`src/scss/pages/_recruit.scss`に追記)
188
+ - `src/js/app.js` 自動更新(Accordion.tsを追加)
189
+
190
+ **生成されるコードの特徴**:
191
+
192
+ ✅ **既存スクリプトを使用**: astro-devの`Accordion.ts`を活用
193
+ ✅ **Mixinを使用**: `@include mq()`、`@include hover()`、`@include fontsize()`
194
+ ✅ **コンテナ制御**: `.contentInner`の二重設定を防止
195
+ ✅ **スタイル分離**: SCSSファイルに分離(Astroファイル内に`<style>`なし)
174
196
 
175
197
  ---
176
198
 
@@ -369,7 +391,32 @@ astro-mcp/
369
391
 
370
392
  ---
371
393
 
372
- ## サポートするセクションタイプ
394
+ ## サポートするUIパターン
395
+
396
+ ### インタラクティブパターン(スクリプト連携)
397
+
398
+ - **`tab`**: タブUI(Tab.ts連携)
399
+ - 自動的に`app.js`に`Tab.ts`を登録
400
+ - ARIA属性・キーボード操作対応
401
+ - **`accordion`**: アコーディオンUI(Accordion.ts連携)
402
+ - 自動的に`app.js`に`Accordion.ts`を登録
403
+ - 高さアニメーション・フォーカス管理
404
+ - **`modal`**: モーダルギャラリー(Modal.ts連携)
405
+ - 自動的に`app.js`に`Modal.ts`を登録
406
+ - 動画/画像/カスタムdialog対応
407
+
408
+ ### 静的パターン
409
+
410
+ - **`grid`**: グリッドレイアウト
411
+ - レスポンシブカラム数制御
412
+ - 画像サポート(Pictureコンポーネント対応)
413
+ - **`carousel`**: カルーセル
414
+ - Swiper.js連携想定
415
+ - 自動再生オプション
416
+ - **`list`**: シンプルリスト
417
+ - 基本的な情報表示
418
+
419
+ ### セクションタイプ
373
420
 
374
421
  - `hero`: ヒーローセクション
375
422
  - `articles`: 記事一覧
@@ -0,0 +1,21 @@
1
+ /**
2
+ * app.js エディター
3
+ * UIパターンに応じて必要なスクリプトを自動登録
4
+ */
5
+ import type { UIPattern } from '../templates/uiPatterns.js';
6
+ /**
7
+ * UIパターンから必要なスクリプトクラス名を取得
8
+ */
9
+ export declare function getRequiredScripts(pattern: UIPattern): string[];
10
+ /**
11
+ * app.js にスクリプトを追加
12
+ * @param originalContent 既存のapp.jsの内容
13
+ * @param scripts 追加するスクリプトクラス名の配列
14
+ * @returns 更新後のapp.jsの内容
15
+ */
16
+ export declare function updateAppJs(originalContent: string, scripts: string[]): string;
17
+ /**
18
+ * app.js の更新が必要かチェック
19
+ */
20
+ export declare function needsAppJsUpdate(originalContent: string, pattern: UIPattern): boolean;
21
+ //# sourceMappingURL=appJsEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appJsEditor.d.ts","sourceRoot":"","sources":["../../src/editors/appJsEditor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,GAAG,MAAM,EAAE,CAW/D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAC1B,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EAAE,GACf,MAAM,CAgGR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC/B,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,SAAS,GAChB,OAAO,CAcT"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * app.js エディター
3
+ * UIパターンに応じて必要なスクリプトを自動登録
4
+ */
5
+ /**
6
+ * UIパターンから必要なスクリプトクラス名を取得
7
+ */
8
+ export function getRequiredScripts(pattern) {
9
+ const scriptMap = {
10
+ tab: ['Tab'],
11
+ accordion: ['Accordion'],
12
+ modal: ['Modal'],
13
+ carousel: [], // カルーセルは外部ライブラリ(Swiper等)を使用
14
+ grid: [],
15
+ list: [],
16
+ };
17
+ return scriptMap[pattern] || [];
18
+ }
19
+ /**
20
+ * app.js にスクリプトを追加
21
+ * @param originalContent 既存のapp.jsの内容
22
+ * @param scripts 追加するスクリプトクラス名の配列
23
+ * @returns 更新後のapp.jsの内容
24
+ */
25
+ export function updateAppJs(originalContent, scripts) {
26
+ if (scripts.length === 0)
27
+ return originalContent;
28
+ const lines = originalContent.split('\n');
29
+ const importLines = [];
30
+ const initLines = [];
31
+ let loadListenerIndex = -1;
32
+ // 既存のimport文とnew呼び出しを解析
33
+ const existingImports = new Set();
34
+ const existingInits = new Set();
35
+ lines.forEach((line, index) => {
36
+ // import文の検出
37
+ const importMatch = line.match(/import\s+{\s*(\w+)\s*}\s+from/);
38
+ if (importMatch) {
39
+ existingImports.add(importMatch[1]);
40
+ }
41
+ // new呼び出しの検出
42
+ const initMatch = line.match(/new\s+(\w+)\(\)/);
43
+ if (initMatch) {
44
+ existingInits.add(initMatch[1]);
45
+ }
46
+ // window.addEventListener("load") の検出
47
+ if (line.includes('window.addEventListener("load"')) {
48
+ loadListenerIndex = index;
49
+ }
50
+ });
51
+ // 追加が必要なスクリプトをフィルタリング
52
+ const scriptsToAdd = scripts.filter((script) => !existingImports.has(script) && !existingInits.has(script));
53
+ if (scriptsToAdd.length === 0) {
54
+ // すべて既に登録済み
55
+ return originalContent;
56
+ }
57
+ // 新しいimport文を生成
58
+ scriptsToAdd.forEach((script) => {
59
+ importLines.push(`import { ${script} } from "./class/${script}.ts";`);
60
+ initLines.push(` new ${script}();`);
61
+ });
62
+ // app.jsの構造を解析して適切な位置に挿入
63
+ let result = originalContent;
64
+ // 1. import文の追加
65
+ // findLastIndex相当の処理(ES2023未満でも動作)
66
+ let lastImportIndex = -1;
67
+ for (let i = lines.length - 1; i >= 0; i--) {
68
+ if (lines[i].match(/^import\s+/)) {
69
+ lastImportIndex = i;
70
+ break;
71
+ }
72
+ }
73
+ if (lastImportIndex !== -1) {
74
+ // 既存のimport文の後に追加
75
+ const before = lines.slice(0, lastImportIndex + 1).join('\n');
76
+ const after = lines.slice(lastImportIndex + 1).join('\n');
77
+ result = before + '\n' + importLines.join('\n') + '\n' + after;
78
+ }
79
+ else {
80
+ // import文がない場合は先頭に追加
81
+ result = importLines.join('\n') + '\n' + originalContent;
82
+ }
83
+ // 2. new呼び出しの追加
84
+ if (loadListenerIndex !== -1) {
85
+ // window.addEventListener("load") ブロック内に追加
86
+ const updatedLines = result.split('\n');
87
+ const loadListenerLineInUpdated = updatedLines.findIndex((line) => line.includes('window.addEventListener("load"'));
88
+ if (loadListenerLineInUpdated !== -1) {
89
+ // 最後のnew呼び出しの後に追加
90
+ let lastInitIndex = loadListenerLineInUpdated;
91
+ for (let i = loadListenerLineInUpdated + 1; i < updatedLines.length; i++) {
92
+ if (updatedLines[i].includes('new ')) {
93
+ lastInitIndex = i;
94
+ }
95
+ if (updatedLines[i].includes('});')) {
96
+ break;
97
+ }
98
+ }
99
+ const before = updatedLines.slice(0, lastInitIndex + 1).join('\n');
100
+ const after = updatedLines.slice(lastInitIndex + 1).join('\n');
101
+ result = before + '\n' + initLines.join('\n') + '\n' + after;
102
+ }
103
+ }
104
+ return result;
105
+ }
106
+ /**
107
+ * app.js の更新が必要かチェック
108
+ */
109
+ export function needsAppJsUpdate(originalContent, pattern) {
110
+ const requiredScripts = getRequiredScripts(pattern);
111
+ if (requiredScripts.length === 0)
112
+ return false;
113
+ // すべてのスクリプトが既に登録されているかチェック
114
+ return requiredScripts.some((script) => {
115
+ const importPattern = new RegExp(`import\\s+{\\s*${script}\\s*}\\s+from`);
116
+ const initPattern = new RegExp(`new\\s+${script}\\(\\)`);
117
+ return (!importPattern.test(originalContent) || !initPattern.test(originalContent));
118
+ });
119
+ }
120
+ //# sourceMappingURL=appJsEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appJsEditor.js","sourceRoot":"","sources":["../../src/editors/appJsEditor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * UIパターンに対応するSCSSテンプレート生成
3
+ * astro-devプロジェクトのmixin・命名規則に準拠
4
+ */
5
+ import type { UIPattern } from './uiPatterns.js';
6
+ export interface ScssPatternConfig {
7
+ pattern: UIPattern;
8
+ pageName: string;
9
+ sectionName: string;
10
+ options?: {
11
+ colors?: {
12
+ primary?: string;
13
+ secondary?: string;
14
+ text?: string;
15
+ };
16
+ spacing?: {
17
+ sectionPadding?: string;
18
+ itemGap?: string;
19
+ };
20
+ columns?: number;
21
+ hasImage?: boolean;
22
+ };
23
+ }
24
+ /**
25
+ * UIパターンに基づいてSCSSを生成
26
+ */
27
+ export declare function generateScssPattern(config: ScssPatternConfig): string;
28
+ //# sourceMappingURL=scssPatterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scssPatterns.d.ts","sourceRoot":"","sources":["../../src/templates/scssPatterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE;QACT,MAAM,CAAC,EAAE;YACR,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,IAAI,CAAC,EAAE,MAAM,CAAC;SACd,CAAC;QACF,OAAO,CAAC,EAAE;YACT,cAAc,CAAC,EAAE,MAAM,CAAC;YACxB,OAAO,CAAC,EAAE,MAAM,CAAC;SACjB,CAAC;QACF,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CACF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAiBrE"}