カリキュラムからレッスン番号を指定してJavaScript学習教材のmdファイルを生成する。ユーザーが「レッスンXXの教材を作成して」と依頼したときに使用する。
curriculum.mdからレッスン情報を抽出し、詳細な解説付きの学習教材を生成する。
そのレッスンまでに学んだ概念だけを使用すること。
関数やVitestテストは、関数を学ぶレッスン以降でのみ使用する。
各セクションで以下の内容を含めて、十分な説明を行う。
概念説明セクション
練習問題セクション
まとめセクション
curriculum.mdを読み込み、指定されたレッスン番号の以下の情報を抽出する:
また、前のレッスン(レッスン番号-1)の情報も抽出して「前回の復習」に使用する。
指定されたレッスン番号より前のレッスンを確認し、どの概念が既に学習済みかを把握する。 練習問題では、既習の概念のみを使用する。
以下の構成で教材を生成する。
## はじめに
- 歓迎メッセージ(不安への共感、励まし)
- このカリキュラムで作れるようになるもの(具体的なアプリ例)
- 学習のコツ(毎日少しずつ、手を動かす、間違いを恐れない)
## 今回の学習
- なぜJavaScriptを学ぶのか(身近なサービスの具体例:YouTube、Amazon、Twitter)
- 今回の目標
## [概念の説明]
- 詳細な説明(身近な例え)
## [実践セクション]
- 手順の詳細な説明
- コードの意味の解説
## 練習問題
## まとめ
## 今回の学習
- 前回の復習
- 今回の目標
## [概念の説明]
## [実践セクション]
## 練習問題
## まとめ
YAMLフロントマター:
今回の学習セクション:
概念説明セクション:
練習問題セクション(すべてのレッスンで共通形式):
exercises/lesson-XXX/index.html を使用してください。このファイルは既に用意されています。各課題のコードを <script> タグの中に入力し、ブラウザで開いて動作を確認しましょう。」exercises/lesson-XXX/ フォルダに以下のファイルが用意されています。」index.html - HTML要素を追加するファイル」script.js - JavaScriptコードを書くファイル」index.html のコメント部分に追加し、JavaScriptコードは script.js に記述してください。ブラウザで index.html を開いて動作を確認しましょう。」テストケース作成のガイドライン(レッスン4以降すべて):
exercises/lesson-XXX/index.test.js に作成まとめセクション:
レッスンの進度に応じて生成するファイルが異なる。
materials/
└── lesson-XXX.md # 教材本体のみ
生成ファイル:
materials/lesson-XXX.md - 教材本体materials/
└── lesson-XXX.md # 教材本体
exercises/
└── lesson-XXX/
├── index.html # HTMLテンプレート
└── index.test.js # テストファイル(講師側が用意)
solutions/
└── lesson-XXX/
└── index.html # 解答ファイル
生成ファイル:
materials/lesson-XXX.md - 教材本体exercises/lesson-XXX/index.html - HTMLテンプレート(学習者が編集)exercises/lesson-XXX/index.test.js - Vitestテスト(講師が用意)solutions/lesson-XXX/index.html - 解答コードindex.htmlの内容:
<script>
// ここにコードを書いてください
</script>
index.test.jsの内容例(変数を確認する形式):
import { describe, it, expect, beforeEach } from 'vitest';
import { JSDOM } from 'jsdom';
import fs from 'fs';
import path from 'path';
describe('Lesson XXX: [レッスンタイトル]', () => {
let dom;
let window;
let document;
beforeEach(() => {
const html = fs.readFileSync(
path.resolve(__dirname, 'index.html'),
'utf-8'
);
dom = new JSDOM(html, { runScripts: 'dangerously' });
window = dom.window;
document = window.document;
});
it('[テスト内容の説明]', () => {
// テストコード
expect(window.変数名).toBe(期待値);
});
// 追加のテストケース...
});
materials/
└── lesson-XXX.md # 教材本体
exercises/
└── lesson-XXX/
├── index.html # HTMLファイル
├── script.js # 外部JavaScriptファイル
└── index.test.js # テストファイル(講師側が用意)
solutions/
└── lesson-XXX/
├── index.html # 解答HTMLファイル
└── script.js # 解答JSファイル
生成ファイル:
materials/lesson-XXX.md - 教材本体exercises/lesson-XXX/index.html - HTMLテンプレートexercises/lesson-XXX/script.js - 外部JSファイルexercises/lesson-XXX/index.test.js - Vitestテスト(講師が用意)solutions/lesson-XXX/index.html - 解答HTMLsolutions/lesson-XXX/script.js - 解答JSindex.htmlの内容:
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lesson XXX</title>
</head>
<body>
<!-- ここにHTML要素を追加してください -->
<script src="script.js"></script>
</body>
</html>
script.jsの内容:
// ここにコードを書いてください
index.test.jsの内容例(DOM要素を確認する形式):
import { describe, it, expect, beforeEach } from 'vitest';
import { JSDOM } from 'jsdom';
import fs from 'fs';
import path from 'path';
describe('Lesson XXX: [レッスンタイトル]', () => {
let dom;
let document;
beforeEach(() => {
const html = fs.readFileSync(
path.resolve(__dirname, 'index.html'),
'utf-8'
);
const js = fs.readFileSync(
path.resolve(__dirname, 'script.js'),
'utf-8'
);
dom = new JSDOM(html, {
runScripts: 'outside-only',
resources: 'usable'
});
document = dom.window.document;
// JavaScriptを実行
const scriptEl = document.createElement('script');
scriptEl.textContent = js;
document.body.appendChild(scriptEl);
});
it('[テスト内容の説明]', () => {
const element = document.getElementById('要素ID');
expect(element).not.toBeNull();
expect(element.textContent).toBe('期待値');
});
// 追加のテストケース...
});
ディレクトリが存在しない場合は自動作成する。
ユーザー: 「レッスン1の教材を作成して」 → materials/lesson-001.md を生成
ユーザー: 「レッスン13の教材を生成」 → materials/lesson-013.md を生成(関数を学んだ後ならexercises/とsolutions/も生成)