zettelkasten-starter 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Enokisan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # 私のZettelkasten
2
+
3
+ Zettelkastenメソッドを使った知識管理システムへようこそ!
4
+
5
+ ## 📁 ディレクトリ構造
6
+
7
+ このプロジェクトは4つの基本的なノートタイプで構成されています:
8
+
9
+ ### 01_FleetingNote(フリーティングノート)
10
+
11
+ - 瞬間的なアイデアや思いつき
12
+ - 後で整理するための一時的なメモ
13
+ - 短時間で記録する簡潔なノート
14
+
15
+ ### 02_LiteratureNote(文献ノート)
16
+
17
+ - 本、記事、動画などの内容要約
18
+ - 引用や参考文献の記録
19
+ - 自分の言葉での解釈や感想
20
+
21
+ ### 03_PermanentNote(パーマネントノート)
22
+
23
+ - 完全に自分の言葉で表現された知識
24
+ - 他のノートと関連付けられた洞察
25
+ - 長期的に価値のある知見
26
+
27
+ ### 04_StructureNote(構造ノート)
28
+
29
+ - テーマやトピックの概要
30
+ - 関連するノートへのインデックス
31
+ - 知識の地図やナビゲーション
32
+
33
+ ## 💡 使い方のコツ
34
+
35
+ 1. **小さく始める**: まずはFleetingNoteに思いついたことを書く
36
+ 2. **定期的な整理**: FleetingNoteを他のノートタイプに昇格させる
37
+ 3. **リンクを作る**: `[[ノート名]]`で他のノートと関連付ける
38
+ 4. **継続が重要**: 毎日少しずつでも続ける
39
+
40
+ ## 📝 ファイル命名規則
41
+
42
+ - 日付ベース: `YYYY-MM-DD_タイトル.md`
43
+ - ID ベース: `001_タイトル.md`
44
+ - 自由形式: `意味のあるタイトル.md`
45
+
46
+ あなたに合った方法を選んでください!
47
+
48
+ ## 🚀 さあ、始めましょう!
49
+
50
+ 各ディレクトリにサンプルファイルが用意されています。
51
+ それらを参考に、あなた独自のZettelkastenを構築していってください。
52
+
53
+ ---
54
+
55
+ **Happy Note-Taking! 📚✨**
@@ -0,0 +1,217 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const { spawn } = require('child_process');
4
+
5
+ // テスト用の一時ディレクトリ
6
+ const testDir = path.join(__dirname, 'cli-test-output');
7
+
8
+ describe('CLI Tool', () => {
9
+ beforeEach(async () => {
10
+ // 各テスト前にクリーンな状態にする
11
+ await fs.remove(testDir);
12
+ await fs.ensureDir(testDir);
13
+ });
14
+
15
+ afterEach(async () => {
16
+ // 各テスト後にクリーンアップ
17
+ await fs.remove(testDir);
18
+ });
19
+
20
+ const runCLI = (args = [], input = '') => {
21
+ return new Promise((resolve, reject) => {
22
+ const cliPath = path.join(__dirname, '../bin/create-zettelkasten.js');
23
+ const child = spawn('node', [cliPath, ...args], {
24
+ cwd: testDir,
25
+ stdio: ['pipe', 'pipe', 'pipe']
26
+ });
27
+
28
+ let stdout = '';
29
+ let stderr = '';
30
+
31
+ child.stdout.on('data', (data) => {
32
+ stdout += data.toString();
33
+ });
34
+
35
+ child.stderr.on('data', (data) => {
36
+ stderr += data.toString();
37
+ });
38
+
39
+ child.on('close', (code) => {
40
+ resolve({ code, stdout, stderr });
41
+ });
42
+
43
+ child.on('error', (err) => {
44
+ reject(err);
45
+ });
46
+
47
+ if (input) {
48
+ child.stdin.write(input);
49
+ child.stdin.end();
50
+ }
51
+ });
52
+ };
53
+
54
+ test('プロジェクト名を引数で指定してプロジェクトが作成される', async () => {
55
+ const projectName = 'test-project-arg';
56
+ const result = await runCLI([projectName]);
57
+
58
+ expect(result.code).toBe(0);
59
+ expect(result.stdout).toContain('🎉 Zettelkasten project created successfully!');
60
+ expect(result.stdout).toContain(`📁 Location: ${path.join(testDir, projectName)}`);
61
+
62
+ // プロジェクトディレクトリが作成されているか確認
63
+ const projectPath = path.join(testDir, projectName);
64
+ expect(await fs.pathExists(projectPath)).toBe(true);
65
+
66
+ // 基本ディレクトリが作成されているか確認
67
+ expect(await fs.pathExists(path.join(projectPath, '01_FleetingNote'))).toBe(true);
68
+ expect(await fs.pathExists(path.join(projectPath, 'README.md'))).toBe(true);
69
+ }, 10000);
70
+
71
+ test('日本語オプションでプロジェクトが作成される', async () => {
72
+ const projectName = 'test-project-ja';
73
+ const result = await runCLI([projectName, '--lang', 'ja']);
74
+
75
+ expect(result.code).toBe(0);
76
+ expect(result.stdout).toContain('🎉 Zettelkasten project created successfully!');
77
+
78
+ // 日本語のREADMEが作成されているか確認
79
+ const readmePath = path.join(testDir, projectName, 'README.md');
80
+ const readmeContent = await fs.readFile(readmePath, 'utf8');
81
+ expect(readmeContent).toContain('私のZettelkasten');
82
+ }, 10000);
83
+
84
+ test('-lフラグでも言語指定ができる', async () => {
85
+ const projectName = 'test-project-l-flag';
86
+ const result = await runCLI([projectName, '-l', 'ja']);
87
+
88
+ expect(result.code).toBe(0);
89
+
90
+ const readmePath = path.join(testDir, projectName, 'README.md');
91
+ const readmeContent = await fs.readFile(readmePath, 'utf8');
92
+ expect(readmeContent).toContain('私のZettelkasten');
93
+ }, 10000);
94
+
95
+ test('バージョン情報が表示される', async () => {
96
+ const result = await runCLI(['--version']);
97
+
98
+ expect(result.code).toBe(0);
99
+ expect(result.stdout).toContain('1.0.0');
100
+ });
101
+
102
+ test('ヘルプが表示される', async () => {
103
+ const result = await runCLI(['--help']);
104
+
105
+ expect(result.code).toBe(0);
106
+ expect(result.stdout).toContain('Create a Zettelkasten project');
107
+ expect(result.stdout).toContain('Usage:');
108
+ expect(result.stdout).toContain('Options:');
109
+ });
110
+
111
+ test('対話モードでプロジェクト名を入力して作成される', async () => {
112
+ const projectName = 'interactive-project';
113
+ const result = await runCLI([], `${projectName}\n`);
114
+
115
+ expect(result.code).toBe(0);
116
+ expect(result.stdout).toContain('📝 Enter project name:');
117
+ expect(result.stdout).toContain('🎉 Zettelkasten project created successfully!');
118
+
119
+ // プロジェクトが作成されているか確認
120
+ const projectPath = path.join(testDir, projectName);
121
+ expect(await fs.pathExists(projectPath)).toBe(true);
122
+ }, 10000);
123
+
124
+ test('空のプロジェクト名で対話モードが失敗する', async () => {
125
+ const result = await runCLI([], '\n');
126
+
127
+ expect(result.code).toBe(1);
128
+ expect(result.stdout).toContain('❌ Project name cannot be empty');
129
+ }, 10000);
130
+
131
+ test('既存のディレクトリ名を指定しても正常に動作する', async () => {
132
+ const projectName = 'existing-dir';
133
+ const projectPath = path.join(testDir, projectName);
134
+
135
+ // 既存のディレクトリを作成
136
+ await fs.ensureDir(projectPath);
137
+ await fs.writeFile(path.join(projectPath, 'existing.txt'), 'test');
138
+
139
+ const result = await runCLI([projectName]);
140
+
141
+ expect(result.code).toBe(0);
142
+ expect(result.stdout).toContain('🎉 Zettelkasten project created successfully!');
143
+
144
+ // 既存ファイルが残っているか確認
145
+ expect(await fs.pathExists(path.join(projectPath, 'existing.txt'))).toBe(true);
146
+ // 新しいディレクトリも作成されているか確認
147
+ expect(await fs.pathExists(path.join(projectPath, '01_FleetingNote'))).toBe(true);
148
+ }, 10000);
149
+
150
+ test('サポートされていない言語でもエラーにならない', async () => {
151
+ const projectName = 'test-unsupported-lang';
152
+ const result = await runCLI([projectName, '--lang', 'fr']);
153
+
154
+ expect(result.code).toBe(0);
155
+ expect(result.stdout).toContain('🎉 Zettelkasten project created successfully!');
156
+
157
+ // 英語のREADMEが作成されているか確認(フォールバック)
158
+ const readmePath = path.join(testDir, projectName, 'README.md');
159
+ const readmeContent = await fs.readFile(readmePath, 'utf8');
160
+ expect(readmeContent).toContain('My Zettelkasten');
161
+ }, 10000);
162
+
163
+ test('相対パスでプロジェクトが作成される', async () => {
164
+ const projectName = 'relative-path-project';
165
+ const result = await runCLI([projectName]);
166
+
167
+ expect(result.code).toBe(0);
168
+
169
+ // カレントディレクトリ(testDir)にプロジェクトが作成されているか確認
170
+ const projectPath = path.join(testDir, projectName);
171
+ expect(await fs.pathExists(projectPath)).toBe(true);
172
+ expect(result.stdout).toContain(`📁 Location: ${projectPath}`);
173
+ }, 10000);
174
+
175
+ test('使用方法の指示が正しく表示される', async () => {
176
+ const projectName = 'usage-test';
177
+ const result = await runCLI([projectName]);
178
+
179
+ expect(result.code).toBe(0);
180
+ expect(result.stdout).toContain('📝 To get started:');
181
+ expect(result.stdout).toContain(`cd ${projectName}`);
182
+ expect(result.stdout).toContain('Check README.md for guidance');
183
+ }, 10000);
184
+ });
185
+
186
+ describe('CLIエラーハンドリング', () => {
187
+ test('無効なオプションでエラーが発生する', async () => {
188
+ const runCLI = (args = []) => {
189
+ return new Promise((resolve) => {
190
+ const cliPath = path.join(__dirname, '../bin/create-zettelkasten.js');
191
+ const child = spawn('node', [cliPath, ...args], {
192
+ stdio: ['pipe', 'pipe', 'pipe']
193
+ });
194
+
195
+ let stdout = '';
196
+ let stderr = '';
197
+
198
+ child.stdout.on('data', (data) => {
199
+ stdout += data.toString();
200
+ });
201
+
202
+ child.stderr.on('data', (data) => {
203
+ stderr += data.toString();
204
+ });
205
+
206
+ child.on('close', (code) => {
207
+ resolve({ code, stdout, stderr });
208
+ });
209
+ });
210
+ };
211
+
212
+ const result = await runCLI(['--invalid-option']);
213
+
214
+ expect(result.code).not.toBe(0);
215
+ expect(result.stderr).toContain('unknown option');
216
+ });
217
+ });
@@ -0,0 +1,207 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const { createZettelkasten } = require('../lib/creator');
4
+
5
+ // テスト用の一時ディレクトリを管理
6
+ const testDir = path.join(__dirname, 'test-output');
7
+
8
+ describe('Zettelkasten Creator', () => {
9
+ beforeEach(async () => {
10
+ // 各テスト前にクリーンな状態にする
11
+ await fs.remove(testDir);
12
+ });
13
+
14
+ afterEach(async () => {
15
+ // 各テスト後にクリーンアップ
16
+ await fs.remove(testDir);
17
+ });
18
+
19
+ describe('createZettelkasten', () => {
20
+ test('英語版のZettelkastenプロジェクトが正常に作成される', async () => {
21
+ const projectPath = path.join(testDir, 'test-zettelkasten-en');
22
+
23
+ await createZettelkasten(projectPath, 'en');
24
+
25
+ // ディレクトリが作成されているか確認
26
+ expect(await fs.pathExists(projectPath)).toBe(true);
27
+
28
+ // 基本ディレクトリが作成されているか確認
29
+ const expectedDirs = [
30
+ '01_FleetingNote',
31
+ '02_LiteratureNote',
32
+ '03_PermanentNote',
33
+ '04_StructureNote'
34
+ ];
35
+
36
+ for (const dir of expectedDirs) {
37
+ const dirPath = path.join(projectPath, dir);
38
+ expect(await fs.pathExists(dirPath)).toBe(true);
39
+ expect((await fs.stat(dirPath)).isDirectory()).toBe(true);
40
+ }
41
+ });
42
+
43
+ test('日本語版のZettelkastenプロジェクトが正常に作成される', async () => {
44
+ const projectPath = path.join(testDir, 'test-zettelkasten-ja');
45
+
46
+ await createZettelkasten(projectPath, 'ja');
47
+
48
+ // ディレクトリが作成されているか確認
49
+ expect(await fs.pathExists(projectPath)).toBe(true);
50
+
51
+ // README.mdが作成され、日本語コンテンツが含まれているか確認
52
+ const readmePath = path.join(projectPath, 'README.md');
53
+ expect(await fs.pathExists(readmePath)).toBe(true);
54
+
55
+ const readmeContent = await fs.readFile(readmePath, 'utf8');
56
+ expect(readmeContent).toContain('私のZettelkasten');
57
+ expect(readmeContent).toContain('フリーティングノート');
58
+ expect(readmeContent).toContain('ディレクトリ構造');
59
+ });
60
+
61
+ test('英語版のREADMEファイルが正しく作成される', async () => {
62
+ const projectPath = path.join(testDir, 'test-zettelkasten-en');
63
+
64
+ await createZettelkasten(projectPath, 'en');
65
+
66
+ const readmePath = path.join(projectPath, 'README.md');
67
+ expect(await fs.pathExists(readmePath)).toBe(true);
68
+
69
+ const readmeContent = await fs.readFile(readmePath, 'utf8');
70
+ expect(readmeContent).toContain('My Zettelkasten');
71
+ expect(readmeContent).toContain('FleetingNote');
72
+ expect(readmeContent).toContain('Directory Structure');
73
+ expect(readmeContent).toContain('Happy Note-Taking!');
74
+ });
75
+
76
+ test('サンプルファイルが正しく作成される', async () => {
77
+ const projectPath = path.join(testDir, 'test-zettelkasten-sample');
78
+
79
+ await createZettelkasten(projectPath, 'en');
80
+
81
+ // 各ディレクトリにサンプルファイルが作成されているか確認
82
+ const fleetingNotePath = path.join(projectPath, '01_FleetingNote');
83
+ const literatureNotePath = path.join(projectPath, '02_LiteratureNote');
84
+ const permanentNotePath = path.join(projectPath, '03_PermanentNote');
85
+ const structureNotePath = path.join(projectPath, '04_StructureNote');
86
+
87
+ // 各ディレクトリにファイルが存在することを確認
88
+ const fleetingFiles = await fs.readdir(fleetingNotePath);
89
+ const literatureFiles = await fs.readdir(literatureNotePath);
90
+ const permanentFiles = await fs.readdir(permanentNotePath);
91
+ const structureFiles = await fs.readdir(structureNotePath);
92
+
93
+ expect(fleetingFiles.length).toBeGreaterThan(0);
94
+ expect(literatureFiles.length).toBeGreaterThan(0);
95
+ expect(permanentFiles.length).toBeGreaterThan(0);
96
+ expect(structureFiles.length).toBeGreaterThan(0);
97
+
98
+ // サンプルファイルの内容を確認
99
+ const sampleFleetingFile = path.join(fleetingNotePath, fleetingFiles[0]);
100
+ const content = await fs.readFile(sampleFleetingFile, 'utf8');
101
+ expect(content).toBeTruthy();
102
+ expect(content.length).toBeGreaterThan(0);
103
+ });
104
+
105
+ test('既存のディレクトリに対しても正常に動作する', async () => {
106
+ const projectPath = path.join(testDir, 'existing-dir');
107
+
108
+ // 既存のディレクトリを作成
109
+ await fs.ensureDir(projectPath);
110
+ await fs.writeFile(path.join(projectPath, 'existing-file.txt'), 'existing content');
111
+
112
+ await createZettelkasten(projectPath, 'en');
113
+
114
+ // 既存ファイルが残っているか確認
115
+ expect(await fs.pathExists(path.join(projectPath, 'existing-file.txt'))).toBe(true);
116
+
117
+ // 新しいディレクトリも作成されているか確認
118
+ expect(await fs.pathExists(path.join(projectPath, '01_FleetingNote'))).toBe(true);
119
+ expect(await fs.pathExists(path.join(projectPath, 'README.md'))).toBe(true);
120
+ });
121
+
122
+ test('デフォルト言語は英語である', async () => {
123
+ const projectPath = path.join(testDir, 'test-default-lang');
124
+
125
+ // 言語パラメータを指定せずに呼び出し
126
+ await createZettelkasten(projectPath);
127
+
128
+ const readmePath = path.join(projectPath, 'README.md');
129
+ const readmeContent = await fs.readFile(readmePath, 'utf8');
130
+
131
+ // 英語のコンテンツが含まれているか確認
132
+ expect(readmeContent).toContain('My Zettelkasten');
133
+ expect(readmeContent).not.toContain('私のZettelkasten');
134
+ });
135
+
136
+ test('無効な言語が指定された場合は英語で作成される', async () => {
137
+ const projectPath = path.join(testDir, 'test-invalid-lang');
138
+
139
+ await createZettelkasten(projectPath, 'invalid-language');
140
+
141
+ const readmePath = path.join(projectPath, 'README.md');
142
+ const readmeContent = await fs.readFile(readmePath, 'utf8');
143
+
144
+ // 英語のコンテンツが含まれているか確認
145
+ expect(readmeContent).toContain('My Zettelkasten');
146
+ });
147
+
148
+ test('空の文字列パスでエラーがスローされる', async () => {
149
+ await expect(createZettelkasten('')).rejects.toThrow();
150
+ });
151
+
152
+ test('権限がない場所への作成でエラーがスローされる', async () => {
153
+ // アクセス権限がない場所を指定
154
+ const restrictedPath = '/root/no-permission';
155
+
156
+ await expect(createZettelkasten(restrictedPath)).rejects.toThrow();
157
+ });
158
+ });
159
+
160
+ describe('ファイル構造の検証', () => {
161
+ test('作成されたプロジェクトが期待される構造を持つ', async () => {
162
+ const projectPath = path.join(testDir, 'structure-test');
163
+
164
+ await createZettelkasten(projectPath, 'ja');
165
+
166
+ // ルートレベルのファイル確認
167
+ expect(await fs.pathExists(path.join(projectPath, 'README.md'))).toBe(true);
168
+
169
+ // ディレクトリ構造確認
170
+ const expectedStructure = [
171
+ '01_FleetingNote',
172
+ '02_LiteratureNote',
173
+ '03_PermanentNote',
174
+ '04_StructureNote'
175
+ ];
176
+
177
+ for (const dir of expectedStructure) {
178
+ const dirPath = path.join(projectPath, dir);
179
+ expect(await fs.pathExists(dirPath)).toBe(true);
180
+
181
+ // 各ディレクトリにサンプルファイルが存在することを確認
182
+ const files = await fs.readdir(dirPath);
183
+ expect(files.length).toBeGreaterThan(0);
184
+
185
+ // 少なくとも1つのmarkdownファイルが存在することを確認
186
+ const markdownFiles = files.filter(file => file.endsWith('.md'));
187
+ expect(markdownFiles.length).toBeGreaterThan(0);
188
+ }
189
+ });
190
+
191
+ test('README.mdの内容が適切な形式である', async () => {
192
+ const projectPath = path.join(testDir, 'readme-test');
193
+
194
+ await createZettelkasten(projectPath, 'ja');
195
+
196
+ const readmePath = path.join(projectPath, 'README.md');
197
+ const content = await fs.readFile(readmePath, 'utf8');
198
+
199
+ // Markdownの基本的な要素が含まれているか確認
200
+ expect(content).toMatch(/^#\s/m); // H1ヘッダーが存在
201
+ expect(content).toMatch(/^##\s/m); // H2ヘッダーが存在
202
+ expect(content).toMatch(/^###\s/m); // H3ヘッダーが存在
203
+ expect(content).toContain('`'); // コードブロックが存在
204
+ expect(content).toContain('📁'); // 絵文字が含まれている
205
+ });
206
+ });
207
+ });
@@ -0,0 +1,214 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const { createZettelkasten } = require('../lib/creator');
4
+
5
+ // テスト用の一時ディレクトリ
6
+ const testDir = path.join(__dirname, 'integration-test-output');
7
+
8
+ describe('統合テスト', () => {
9
+ beforeEach(async () => {
10
+ await fs.remove(testDir);
11
+ await fs.ensureDir(testDir);
12
+ });
13
+
14
+ afterEach(async () => {
15
+ await fs.remove(testDir);
16
+ });
17
+
18
+ test('完全なZettelkastenプロジェクトが期待通りに機能する', async () => {
19
+ const projectPath = path.join(testDir, 'full-project');
20
+
21
+ // プロジェクトを作成
22
+ await createZettelkasten(projectPath, 'ja');
23
+
24
+ // 1. プロジェクト構造の完全性確認
25
+ const expectedDirs = [
26
+ '01_FleetingNote',
27
+ '02_LiteratureNote',
28
+ '03_PermanentNote',
29
+ '04_StructureNote'
30
+ ];
31
+
32
+ for (const dir of expectedDirs) {
33
+ const dirPath = path.join(projectPath, dir);
34
+ expect(await fs.pathExists(dirPath)).toBe(true);
35
+
36
+ // 各ディレクトリにサンプルファイルが存在することを確認
37
+ const files = await fs.readdir(dirPath);
38
+ expect(files.length).toBeGreaterThan(0);
39
+
40
+ // 最初のファイルの内容を確認
41
+ const firstFile = files[0];
42
+ const filePath = path.join(dirPath, firstFile);
43
+ const content = await fs.readFile(filePath, 'utf8');
44
+ expect(content.trim().length).toBeGreaterThan(0);
45
+ }
46
+
47
+ // 2. README.mdの内容確認
48
+ const readmePath = path.join(projectPath, 'README.md');
49
+ expect(await fs.pathExists(readmePath)).toBe(true);
50
+
51
+ const readmeContent = await fs.readFile(readmePath, 'utf8');
52
+
53
+ // 必要なセクションが全て含まれているか確認
54
+ expect(readmeContent).toContain('私のZettelkasten');
55
+ expect(readmeContent).toContain('📁 ディレクトリ構造');
56
+ expect(readmeContent).toContain('01_FleetingNote(フリーティングノート)');
57
+ expect(readmeContent).toContain('02_LiteratureNote(文献ノート)');
58
+ expect(readmeContent).toContain('03_PermanentNote(パーマネントノート)');
59
+ expect(readmeContent).toContain('04_StructureNote(構造ノート)');
60
+ expect(readmeContent).toContain('💡 使い方のコツ');
61
+ expect(readmeContent).toContain('🏷️ タグの使い方');
62
+ expect(readmeContent).toContain('📝 ファイル命名規則');
63
+ expect(readmeContent).toContain('🚀 さあ、始めましょう!');
64
+
65
+ // 3. ファイル拡張子の確認
66
+ for (const dir of expectedDirs) {
67
+ const dirPath = path.join(projectPath, dir);
68
+ const files = await fs.readdir(dirPath);
69
+
70
+ for (const file of files) {
71
+ expect(file).toMatch(/\.md$/); // 全てのファイルがMarkdown形式
72
+ }
73
+ }
74
+ });
75
+
76
+ test('英語と日本語のプロジェクトが共存できる', async () => {
77
+ const enProjectPath = path.join(testDir, 'en-project');
78
+ const jaProjectPath = path.join(testDir, 'ja-project');
79
+
80
+ // 英語版プロジェクト作成
81
+ await createZettelkasten(enProjectPath, 'en');
82
+
83
+ // 日本語版プロジェクト作成
84
+ await createZettelkasten(jaProjectPath, 'ja');
85
+
86
+ // 両方のプロジェクトが存在することを確認
87
+ expect(await fs.pathExists(enProjectPath)).toBe(true);
88
+ expect(await fs.pathExists(jaProjectPath)).toBe(true);
89
+
90
+ // 英語版READMEの確認
91
+ const enReadme = await fs.readFile(path.join(enProjectPath, 'README.md'), 'utf8');
92
+ expect(enReadme).toContain('My Zettelkasten');
93
+ expect(enReadme).toContain('Directory Structure');
94
+
95
+ // 日本語版READMEの確認
96
+ const jaReadme = await fs.readFile(path.join(jaProjectPath, 'README.md'), 'utf8');
97
+ expect(jaReadme).toContain('私のZettelkasten');
98
+ expect(jaReadme).toContain('ディレクトリ構造');
99
+
100
+ // 両プロジェクトが同じディレクトリ構造を持つことを確認
101
+ const enDirs = await fs.readdir(enProjectPath);
102
+ const jaDirs = await fs.readdir(jaProjectPath);
103
+
104
+ const expectedDirs = [
105
+ '01_FleetingNote',
106
+ '02_LiteratureNote',
107
+ '03_PermanentNote',
108
+ '04_StructureNote',
109
+ 'README.md'
110
+ ];
111
+
112
+ expectedDirs.forEach(item => {
113
+ expect(enDirs).toContain(item);
114
+ expect(jaDirs).toContain(item);
115
+ });
116
+ });
117
+
118
+ test('既存ファイルがある環境での安全な作成', async () => {
119
+ const projectPath = path.join(testDir, 'existing-content');
120
+
121
+ // 既存コンテンツを作成
122
+ await fs.ensureDir(projectPath);
123
+ await fs.writeFile(path.join(projectPath, 'my-notes.md'), '# 既存のメモ\n重要な内容');
124
+ await fs.ensureDir(path.join(projectPath, 'custom-folder'));
125
+ await fs.writeFile(path.join(projectPath, 'custom-folder', 'data.txt'), 'カスタムデータ');
126
+
127
+ // Zettelkastenプロジェクトを追加
128
+ await createZettelkasten(projectPath, 'ja');
129
+
130
+ // 既存ファイルが保持されているか確認
131
+ expect(await fs.pathExists(path.join(projectPath, 'my-notes.md'))).toBe(true);
132
+ expect(await fs.pathExists(path.join(projectPath, 'custom-folder', 'data.txt'))).toBe(true);
133
+
134
+ const existingContent = await fs.readFile(path.join(projectPath, 'my-notes.md'), 'utf8');
135
+ expect(existingContent).toContain('重要な内容');
136
+
137
+ // 新しいZettelkastenディレクトリも作成されているか確認
138
+ expect(await fs.pathExists(path.join(projectPath, '01_FleetingNote'))).toBe(true);
139
+ expect(await fs.pathExists(path.join(projectPath, 'README.md'))).toBe(true);
140
+ });
141
+
142
+ test('サンプルファイルの品質確認', async () => {
143
+ const projectPath = path.join(testDir, 'sample-quality');
144
+
145
+ await createZettelkasten(projectPath, 'ja');
146
+
147
+ const directories = [
148
+ '01_FleetingNote',
149
+ '02_LiteratureNote',
150
+ '03_PermanentNote',
151
+ '04_StructureNote'
152
+ ];
153
+
154
+ for (const dir of directories) {
155
+ const dirPath = path.join(projectPath, dir);
156
+ const files = await fs.readdir(dirPath);
157
+
158
+ for (const file of files) {
159
+ const filePath = path.join(dirPath, file);
160
+ const content = await fs.readFile(filePath, 'utf8');
161
+
162
+ // Markdownファイルの基本的な品質確認
163
+ expect(content).toMatch(/^#/m); // ヘッダーが存在
164
+ expect(content.length).toBeGreaterThan(50); // 適度な長さ
165
+ expect(content).toContain('\n'); // 複数行
166
+
167
+ // 日本語のサンプルファイルであることを確認
168
+ expect(content).toMatch(/[ひらがなカタカナ漢字]/);
169
+ }
170
+ }
171
+ });
172
+
173
+ test('大量のファイル作成でもパフォーマンスが問題ない', async () => {
174
+ const startTime = Date.now();
175
+
176
+ // 複数のプロジェクトを連続作成
177
+ const projectPromises = [];
178
+ for (let i = 0; i < 5; i++) {
179
+ const projectPath = path.join(testDir, `performance-test-${i}`);
180
+ projectPromises.push(createZettelkasten(projectPath, i % 2 === 0 ? 'en' : 'ja'));
181
+ }
182
+
183
+ await Promise.all(projectPromises);
184
+
185
+ const endTime = Date.now();
186
+ const elapsedTime = endTime - startTime;
187
+
188
+ // 5秒以内に完了することを確認(合理的なパフォーマンス要件)
189
+ expect(elapsedTime).toBeLessThan(5000);
190
+
191
+ // 全てのプロジェクトが正常に作成されたことを確認
192
+ for (let i = 0; i < 5; i++) {
193
+ const projectPath = path.join(testDir, `performance-test-${i}`);
194
+ expect(await fs.pathExists(projectPath)).toBe(true);
195
+ expect(await fs.pathExists(path.join(projectPath, 'README.md'))).toBe(true);
196
+ }
197
+ });
198
+
199
+ test('エラー発生後の状態確認', async () => {
200
+ const projectPath = path.join(testDir, 'error-recovery');
201
+
202
+ // 権限のないディレクトリの親を作成してから権限を変更する代わりに
203
+ // 無効なパス文字を使用してエラーを発生させる
204
+ const invalidPath = path.join(testDir, 'invalid\x00path');
205
+
206
+ await expect(createZettelkasten(invalidPath, 'ja')).rejects.toThrow();
207
+
208
+ // その後正常なプロジェクト作成ができることを確認
209
+ await createZettelkasten(projectPath, 'ja');
210
+
211
+ expect(await fs.pathExists(projectPath)).toBe(true);
212
+ expect(await fs.pathExists(path.join(projectPath, 'README.md'))).toBe(true);
213
+ });
214
+ });
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { program } = require('commander');
4
+ const path = require('path');
5
+ const readline = require('readline');
6
+ const { createZettelkasten } = require('../lib/creator');
7
+
8
+ /**
9
+ * 対話的にプロジェクト名を取得
10
+ */
11
+ function askProjectName() {
12
+ return new Promise((resolve) => {
13
+ const rl = readline.createInterface({
14
+ input: process.stdin,
15
+ output: process.stdout
16
+ });
17
+
18
+ rl.question('📝 Enter project name: ', (answer) => {
19
+ rl.close();
20
+ const projectName = answer.trim();
21
+ if (projectName === '') {
22
+ console.log('❌ Project name cannot be empty. Please try again.');
23
+ process.exit(1);
24
+ }
25
+ resolve(projectName);
26
+ });
27
+ });
28
+ }
29
+
30
+ program
31
+ .version('1.0.0')
32
+ .argument('[project-name]', 'Project name (optional - will prompt if not provided)')
33
+ .option('-l, --lang <language>', 'Generation language (en|ja)', 'en')
34
+ .description('Create a Zettelkasten project')
35
+ .action(async (projectName, options) => {
36
+ try {
37
+ // プロジェクト名が提供されていない場合は対話モードで取得
38
+ if (!projectName) {
39
+ projectName = await askProjectName();
40
+ }
41
+
42
+ const targetPath = path.resolve(process.cwd(), projectName);
43
+ await createZettelkasten(targetPath, options.lang);
44
+
45
+ console.log('🎉 Zettelkasten project created successfully!');
46
+ console.log(`📁 Location: ${targetPath}`);
47
+ console.log(`\n📝 To get started:`);
48
+ console.log(` cd ${projectName}`);
49
+ console.log(` Check README.md for guidance`);
50
+ } catch (error) {
51
+ console.error('❌ Error occurred:', error.message);
52
+ process.exit(1);
53
+ }
54
+ });
55
+
56
+ program.parse();
package/index.js ADDED
@@ -0,0 +1,5 @@
1
+ const { createZettelkasten } = require('./lib/creator');
2
+
3
+ module.exports = {
4
+ createZettelkasten
5
+ };
package/lib/creator.js ADDED
@@ -0,0 +1,553 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * Zettelkastenプロジェクトを作成する
6
+ * @param {string} targetPath - 作成先のパス
7
+ * @param {string} language - 言語 ('en' | 'ja')
8
+ */
9
+ async function createZettelkasten(targetPath, language = 'en') {
10
+ // ディレクトリが存在しない場合は作成
11
+ await fs.ensureDir(targetPath);
12
+
13
+ // 4つの基本ディレクトリを作成
14
+ const directories = [
15
+ '01_FleetingNote',
16
+ '02_LiteratureNote',
17
+ '03_PermanentNote',
18
+ '04_StructureNote'
19
+ ];
20
+
21
+ for (const dir of directories) {
22
+ await fs.ensureDir(path.join(targetPath, dir));
23
+ }
24
+
25
+ // README.mdを作成
26
+ const readmeContent = getReadmeContent(language);
27
+ await fs.writeFile(path.join(targetPath, 'README.md'), readmeContent);
28
+
29
+ // サンプルファイルを作成
30
+ await createSampleFiles(targetPath, language);
31
+ }
32
+
33
+ /**
34
+ * 言語に応じたREADMEコンテンツを取得
35
+ * @param {string} language - 言語
36
+ * @returns {string} READMEの内容
37
+ */
38
+ function getReadmeContent(language) {
39
+ if (language === 'ja') {
40
+ return `# 私のZettelkasten
41
+
42
+ Zettelkastenメソッドを使った知識管理システムへようこそ!
43
+
44
+ ## 📁 ディレクトリ構造
45
+
46
+ このプロジェクトは4つの基本的なノートタイプで構成されています:
47
+
48
+ ### 01_FleetingNote(フリーティングノート)
49
+
50
+ - 瞬間的なアイデアや思いつき
51
+ - 後で整理するための一時的なメモ
52
+ - 短時間で記録する簡潔なノート
53
+
54
+ ### 02_LiteratureNote(文献ノート)
55
+
56
+ - 本、記事、動画などの内容要約
57
+ - 引用や参考文献の記録
58
+ - 自分の言葉での解釈や感想
59
+
60
+ ### 03_PermanentNote(パーマネントノート)
61
+
62
+ - 完全に自分の言葉で表現された知識
63
+ - 他のノートと関連付けられた洞察
64
+ - 長期的に価値のある知見
65
+
66
+ ### 04_StructureNote(構造ノート)
67
+
68
+ - テーマやトピックの概要
69
+ - 関連するノートへのインデックス
70
+ - 知識の地図やナビゲーション
71
+
72
+ ## 💡 使い方のコツ
73
+
74
+ 1. **小さく始める**: まずはFleetingNoteに思いついたことを書く
75
+ 2. **定期的な整理**: FleetingNoteを他のノートタイプに昇格させる
76
+ 3. **リンクを作る**: \`[[ノート名]]\`で他のノートと関連付ける
77
+ 4. **タグを活用**: \`#concept\` \`#method\` \`#review\`などでカテゴライズ
78
+ 5. **継続が重要**: 毎日少しずつでも続ける
79
+
80
+ ## 🏷️ タグの使い方
81
+
82
+ タグは情報の分類と検索を効率化します:
83
+
84
+ - \`#concept\` - 概念や理論
85
+ - \`#method\` - 方法論やテクニック
86
+ - \`#review\` - 振り返りや評価
87
+ - \`#source/book\` - 書籍からの情報
88
+ - \`#source/article\` - 記事からの情報
89
+ - \`#draft\` - 下書きや未完成
90
+ - \`#important\` - 重要度の高い内容
91
+ - \`#todo\` - アクションアイテム
92
+ - \`#気の赴くままに\` - 好きなタグを追加していきましょう
93
+
94
+ ## 📝 ファイル命名規則
95
+
96
+ - 日付ベース: \`YYYY-MM-DD_タイトル.md\`
97
+ - ID ベース: \`001_タイトル.md\`
98
+ - 自由形式: \`意味のあるタイトル.md\`
99
+
100
+ あなたに合った方法を選んでください!
101
+
102
+ ## 🚀 さあ、始めましょう!
103
+
104
+ 各ディレクトリにサンプルファイルが用意されています。
105
+ それらを参考に、あなた独自のZettelkastenを構築していってください。
106
+
107
+ ---
108
+
109
+ **Happy Note-Taking! 📚✨**
110
+ `;
111
+ } else {
112
+ return `# My Zettelkasten
113
+
114
+ Welcome to your knowledge management system using the Zettelkasten method!
115
+
116
+ ## 📁 Directory Structure
117
+
118
+ This project consists of four basic note types:
119
+
120
+ ### 01_FleetingNote
121
+
122
+ - Fleeting ideas and quick thoughts
123
+ - Temporary notes for later organization
124
+ - Brief notes recorded in a short time
125
+
126
+ ### 02_LiteratureNote
127
+
128
+ - Summaries of books, articles, videos, etc.
129
+ - Citations and references
130
+ - Your interpretations and reflections
131
+
132
+ ### 03_PermanentNote
133
+
134
+ - Knowledge expressed entirely in your own words
135
+ - Insights linked to other notes
136
+ - Long-term valuable insights
137
+
138
+ ### 04_StructureNote
139
+
140
+ - Overview of themes and topics
141
+ - Index to related notes
142
+ - Knowledge maps and navigation
143
+
144
+ ## 💡 Tips for Usage
145
+
146
+ 1. **Start small**: First write down your thoughts in FleetingNote
147
+ 2. **Regular organization**: Promote FleetingNotes to other note types
148
+ 3. **Create links**: Use \`[[Note Name]]\` to connect with other notes
149
+ 4. **Use tags**: Categorize with \`#concept\` \`#method\` \`#review\` etc.
150
+ 5. **Consistency is key**: Continue a little bit every day
151
+
152
+ ## 🏷️ How to Use Tags
153
+
154
+ Tags help organize and search information efficiently:
155
+
156
+ - \`#concept\` - Concepts and theories
157
+ - \`#method\` - Methodologies and techniques
158
+ - \`#review\` - Reflections and evaluations
159
+ - \`#source/book\` - Information from books
160
+ - \`#source/article\` - Information from articles
161
+ - \`#draft\` - Drafts and work in progress
162
+ - \`#important\` - High priority content
163
+ - \`#todo\` - Action items
164
+ - \`#asyouwish\` - Add your own tags as you go
165
+
166
+ ## 📝 File Naming Conventions
167
+
168
+ - Date-based: \`YYYY-MM-DD_title.md\`
169
+ - ID-based: \`001_title.md\`
170
+ - Free-form: \`meaningful-title.md\`
171
+
172
+ Choose the method that works best for you!
173
+
174
+ ## 🚀 Let's Get Started!
175
+
176
+ Sample files are prepared in each directory.
177
+ Use them as references to build your unique Zettelkasten.
178
+
179
+ ---
180
+
181
+ **Happy Note-Taking! 📚✨**
182
+ `;
183
+ }
184
+ }
185
+
186
+ /**
187
+ * サンプルファイルを作成
188
+ * @param {string} targetPath - 作成先のパス
189
+ * @param {string} language - 言語
190
+ */
191
+ async function createSampleFiles(targetPath, language) {
192
+ const samples = getSampleContents(language);
193
+
194
+ for (const [filePath, content] of Object.entries(samples)) {
195
+ await fs.writeFile(path.join(targetPath, filePath), content);
196
+ }
197
+ }
198
+
199
+ /**
200
+ * サンプルファイルの内容を取得
201
+ * @param {string} language - 言語
202
+ * @returns {Object} ファイルパスとコンテンツのオブジェクト
203
+ */
204
+ function getSampleContents(language) {
205
+ if (language === 'ja') {
206
+ return {
207
+ '01_FleetingNote/sample_fleeting.md': `# フリーティングノートのサンプル
208
+
209
+ 日付: ${new Date().toISOString().split('T')[0]}
210
+ タグ: #fleeting #zettelkasten #idea #draft
211
+
212
+ ## 💭 今日の思いつき
213
+
214
+ - Zettelkastenを始めてみた
215
+ - アイデアを素早くキャッチするのが重要
216
+ - 後で整理することを前提に、まずは記録
217
+
218
+ ## 🔗 関連する可能性
219
+
220
+ - [[学習方法について]]
221
+ - [[知識管理システム]]
222
+
223
+ ## 📋 次のアクション
224
+
225
+ - [ ] このアイデアをより詳しく調べる #todo
226
+ - [ ] 関連する文献を探す #todo
227
+
228
+ ---
229
+
230
+ *これはサンプルファイルです。自由に編集・削除してください。*
231
+ `,
232
+ '02_LiteratureNote/sample_literature.md': `# 文献ノートのサンプル
233
+
234
+ タグ: #literature #source/book #zettelkasten #method #notes
235
+
236
+ ## 📚 書籍情報
237
+
238
+ - **タイトル**: How to Take Smart Notes
239
+ - **著者**: Sönke Ahrens
240
+ - **出版年**: 2017
241
+ - **読了日**: ${new Date().toISOString().split('T')[0]}
242
+
243
+ ## 📝 主要ポイント
244
+
245
+ ### Zettelkastenの原則
246
+
247
+ 1. **一つのアイデア、一つのノート**
248
+ - 各ノートは単一のアイデアに焦点を当てる
249
+ - 複雑な概念は複数のノートに分割
250
+
251
+ 2. **自分の言葉で書く**
252
+ - 単なるコピペではなく、理解した内容を表現
253
+ - 後で読み返した時に理解できるように
254
+
255
+ 3. **リンクを作る**
256
+ - ノート間の関連性を明示的に作る
257
+ - 新しい洞察が生まれる可能性
258
+
259
+ ## 🤔 私の考察
260
+
261
+ Zettelkastenは単なるノート取りツールではなく、思考のツールだと感じた。
262
+ 重要なのは... #concept #important
263
+
264
+ ## 💡 アクションアイテム
265
+
266
+ - [ ] 実際にZettelkastenシステムを1週間試してみる #todo
267
+ - [ ] 効果を測定する方法を考える #todo
268
+
269
+ ## 🔗 関連ノート
270
+
271
+ - [[001_zettelkasten_principles]]
272
+ - [[note_taking_methods]]
273
+
274
+ ---
275
+
276
+ *これはサンプルファイルです。実際の読書ノートに置き換えてください。*
277
+ `,
278
+ '03_PermanentNote/sample_permanent.md': `# パーマネントノートのサンプル
279
+
280
+ ID: 001
281
+ 作成日: ${new Date().toISOString().split('T')[0]}
282
+ タグ: #permanent #concept #knowledge-management #connection #important
283
+
284
+ ## 🎯 知識管理における「つながり」の重要性
285
+
286
+ 知識管理システムで最も重要なのは、個々の情報ではなく、それらの**つながり**である。
287
+
288
+ ### なぜつながりが重要なのか
289
+
290
+ 1. **新しい洞察の創出**
291
+ - 異なる分野の知識が結びつくことで、予期しない発見が生まれる
292
+ - 創造性は既存要素の新しい組み合わせから生まれる
293
+
294
+ 2. **理解の深化**
295
+ - 関連する概念と結びつけることで、個別の知識がより深く理解される
296
+ - 文脈の中で知識を捉えることができる
297
+
298
+ 3. **記憶の強化**
299
+ - 関連付けられた情報は、単独の情報よりも記憶に残りやすい
300
+ - 想起の手がかりが増える
301
+
302
+ ### 実践的な方法
303
+
304
+ - 新しいノートを作成する際は、既存の3つ以上のノートとの関連を考える
305
+ - 定期的にノート間のリンクを見直し、新しいつながりを発見する
306
+ - 構造ノートを使って、テーマごとの知識の地図を作る
307
+
308
+ ## 🔗 関連するノート
309
+
310
+ - [[creativity_and_connection]]
311
+ - [[memory_techniques]]
312
+ - [[zettelkasten_principles]]
313
+
314
+ ## 📚 参考文献
315
+
316
+ - Ahrens, S. (2017). How to Take Smart Notes
317
+ - [[literature_note_smart_notes]]
318
+
319
+ ---
320
+
321
+ *これは完全に自分の言葉で表現された知識です。*
322
+ `,
323
+ '04_StructureNote/sample_structure.md': `# 構造ノート: Zettelkastenとは
324
+
325
+ 作成日: ${new Date().toISOString().split('T')[0]}
326
+ タグ: #structure #zettelkasten #index #map #overview
327
+
328
+ ## 🗺️ このトピックの概要
329
+
330
+ このノートは「Zettelkasten」というテーマの入り口として機能します。
331
+ 関連するすべてのノートへのナビゲーションを提供します。
332
+
333
+ ## 📖 基本概念
334
+
335
+ ### Zettelkastenの原則
336
+
337
+ - [[001_zettelkasten_principles]] - 基本的な考え方
338
+ - [[connection_importance]] - つながりの重要性
339
+ - [[atomic_notes]] - アトミックノートの概念
340
+
341
+ ### 実践方法
342
+
343
+ - [[daily_note_routine]] - 日々のノート習慣
344
+ - [[note_linking_strategies]] - リンク戦略
345
+ - [[review_process]] - 定期的な見直し
346
+
347
+ ## 📚 参考文献とソース
348
+
349
+ ### 文献ノート
350
+ - [[literature_note_smart_notes]] - "How to Take Smart Notes"
351
+ - [[literature_note_second_brain]] - "Building a Second Brain"
352
+
353
+ ### フリーティングノート
354
+ - [[fleeting_zettelkasten_discovery]] - Zettelkasten発見時の印象
355
+ - [[fleeting_digital_vs_analog]] - デジタル vs アナログの考察
356
+
357
+ ## 🔍 関連トピック
358
+
359
+ - [[knowledge_management]] - より広い知識管理の文脈
360
+ - [[creative_thinking]] - 創造的思考との関連
361
+ - [[learning_systems]] - 学習システム全般
362
+
363
+ ## 📊 進捗状況
364
+
365
+ - ✅ 基本概念の理解
366
+ - 🔄 実践方法の模索中
367
+ - ⭕ 自分なりのシステム構築(今後の課題)
368
+
369
+ ---
370
+
371
+ *この構造ノートは定期的に更新し、新しいノートが追加されたら関連付けを行います。*
372
+ `
373
+ };
374
+ } else {
375
+ return {
376
+ '01_FleetingNote/sample_fleeting.md': `# Fleeting Note Sample
377
+
378
+ Date: ${new Date().toISOString().split('T')[0]}
379
+ Tags: #fleeting #zettelkasten #idea #draft
380
+
381
+ ## 💭 Today's Ideas
382
+
383
+ - Started using Zettelkasten
384
+ - Quick capture of ideas is crucial
385
+ - Focus on recording first, organizing later
386
+
387
+ ## 🔗 Potential Connections
388
+
389
+ - [[learning_methods]]
390
+ - [[knowledge_management_systems]]
391
+
392
+ ## 📋 Next Actions
393
+
394
+ - [ ] Research this idea further #todo
395
+ - [ ] Find related literature #todo
396
+
397
+ ---
398
+
399
+ *This is a sample file. Feel free to edit or delete.*
400
+ `,
401
+ '02_LiteratureNote/sample_literature.md': `# Literature Note Sample
402
+
403
+ Tags: #literature #source/book #zettelkasten #method #notes
404
+
405
+ ## 📚 Book Information
406
+
407
+ - **Title**: How to Take Smart Notes
408
+ - **Author**: Sönke Ahrens
409
+ - **Year**: 2017
410
+ - **Date Read**: ${new Date().toISOString().split('T')[0]}
411
+
412
+ ## 📝 Key Points
413
+
414
+ ### Zettelkasten Principles
415
+
416
+ 1. **One Idea, One Note**
417
+ - Each note focuses on a single idea
418
+ - Complex concepts are split into multiple notes
419
+
420
+ 2. **Write in Your Own Words**
421
+ - Not just copy-paste, but express understanding
422
+ - Make it understandable when revisiting later
423
+
424
+ 3. **Create Links**
425
+ - Explicitly create relationships between notes
426
+ - Enables emergence of new insights
427
+
428
+ ## 🤔 My Reflections
429
+
430
+ I realized that Zettelkasten is not just a note-taking tool, but a thinking tool.
431
+ The important thing is... #concept #important
432
+
433
+ ## 💡 Action Items
434
+
435
+ - [ ] Try the Zettelkasten system for a week #todo
436
+ - [ ] Think about how to measure effectiveness #todo
437
+
438
+ ## 🔗 Related Notes
439
+
440
+ - [[001_zettelkasten_principles]]
441
+ - [[note_taking_methods]]
442
+
443
+ ---
444
+
445
+ *This is a sample file. Replace with your actual reading notes.*
446
+ `,
447
+ '03_PermanentNote/sample_permanent.md': `# Permanent Note Sample
448
+
449
+ ID: 001
450
+ Created: ${new Date().toISOString().split('T')[0]}
451
+ Tags: #permanent #concept #knowledge-management #connection #important
452
+
453
+ ## 🎯 The Importance of "Connections" in Knowledge Management
454
+
455
+ The most important aspect of knowledge management systems is not individual pieces of information, but their **connections**.
456
+
457
+ ### Why Connections Matter
458
+
459
+ 1. **Creation of New Insights**
460
+
461
+ - Unexpected discoveries emerge when knowledge from different fields connects
462
+ - Creativity comes from new combinations of existing elements
463
+
464
+ 2. **Deepening Understanding**
465
+
466
+ - Knowledge becomes more deeply understood when connected to related concepts
467
+ - Enables understanding knowledge within context
468
+
469
+ 3. **Memory Enhancement**
470
+
471
+ - Connected information is more memorable than isolated information
472
+ - Increases retrieval cues
473
+
474
+ ### Practical Methods
475
+
476
+ - When creating new notes, consider connections to at least 3 existing notes
477
+ - Regularly review links between notes to discover new connections
478
+ - Use structure notes to create knowledge maps by theme
479
+
480
+ ## 🔗 Related Notes
481
+
482
+ - [[creativity_and_connection]]
483
+ - [[memory_techniques]]
484
+ - [[zettelkasten_principles]]
485
+
486
+ ## 📚 References
487
+
488
+ - Ahrens, S. (2017). How to Take Smart Notes
489
+ - [[literature_note_smart_notes]]
490
+
491
+ ---
492
+
493
+ *This knowledge is expressed entirely in my own words.*
494
+ `,
495
+ '04_StructureNote/sample_structure.md': `# Structure Note: What is Zettelkasten
496
+
497
+ Created: ${new Date().toISOString().split('T')[0]}
498
+ Tags: #structure #zettelkasten #index #map #overview
499
+
500
+ ## 🗺️ Topic Overview
501
+
502
+ This note serves as an entry point for the "Zettelkasten" theme.
503
+ It provides navigation to all related notes.
504
+
505
+ ## 📖 Core Concepts
506
+
507
+ ### Zettelkasten Principles
508
+
509
+ - [[001_zettelkasten_principles]] - Basic philosophy
510
+ - [[connection_importance]] - Importance of connections
511
+ - [[atomic_notes]] - Atomic note concept
512
+
513
+ ### Practical Methods
514
+
515
+ - [[daily_note_routine]] - Daily note-taking habits
516
+ - [[note_linking_strategies]] - Linking strategies
517
+ - [[review_process]] - Regular review process
518
+
519
+ ## 📚 References and Sources
520
+
521
+ ### Literature Notes
522
+
523
+ - [[literature_note_smart_notes]] - "How to Take Smart Notes"
524
+ - [[literature_note_second_brain]] - "Building a Second Brain"
525
+
526
+ ### Fleeting Notes
527
+
528
+ - [[fleeting_zettelkasten_discovery]] - First impressions of Zettelkasten
529
+ - [[fleeting_digital_vs_analog]] - Digital vs Analog considerations
530
+
531
+ ## 🔍 Related Topics
532
+
533
+ - [[knowledge_management]] - Broader knowledge management context
534
+ - [[creative_thinking]] - Connection to creative thinking
535
+ - [[learning_systems]] - Learning systems in general
536
+
537
+ ## 📊 Progress Status
538
+
539
+ - ✅ Understanding basic concepts
540
+ - 🔄 Exploring practical methods
541
+ - ⭕ Building personal system (future goal)
542
+
543
+ ---
544
+
545
+ *This structure note will be updated regularly, and new connections will be made as notes are added.*
546
+ `
547
+ };
548
+ }
549
+ }
550
+
551
+ module.exports = {
552
+ createZettelkasten
553
+ };
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "zettelkasten-starter",
3
+ "version": "1.0.0",
4
+ "description": "Zettelkasten-Starter is an ultimately simple library for a zettelkasten beginner",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "create-zettelkasten": "bin/create-zettelkasten.js"
8
+ },
9
+ "scripts": {
10
+ "test": "jest",
11
+ "test:watch": "jest --watch",
12
+ "test:coverage": "jest --coverage"
13
+ },
14
+ "keywords": [
15
+ "zettelkasten",
16
+ "note-taking",
17
+ "knowledge-management",
18
+ "pkm",
19
+ "markdown",
20
+ "cli"
21
+ ],
22
+ "author": "Enokisan",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/Enokisan/zettelkasten-starter.git"
27
+ },
28
+ "homepage": "https://github.com/Enokisan/zettelkasten-starter#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/Enokisan/zettelkasten-starter/issues"
31
+ },
32
+ "dependencies": {
33
+ "commander": "^9.5.0",
34
+ "fs-extra": "^11.2.0"
35
+ },
36
+ "devDependencies": {
37
+ "jest": "^29.7.0",
38
+ "@types/jest": "^29.5.5"
39
+ },
40
+ "engines": {
41
+ "node": ">=14.0.0"
42
+ },
43
+ "jest": {
44
+ "testEnvironment": "node",
45
+ "collectCoverageFrom": [
46
+ "lib/**/*.js",
47
+ "bin/**/*.js",
48
+ "!node_modules/**"
49
+ ],
50
+ "coverageDirectory": "coverage",
51
+ "coverageReporters": [
52
+ "text",
53
+ "lcov",
54
+ "html"
55
+ ]
56
+ }
57
+ }