mdjournal 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/README.md +209 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +601 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +100 -0
- package/dist/index.js.map +1 -0
- package/dist/routes/calendar.d.ts +8 -0
- package/dist/routes/calendar.d.ts.map +1 -0
- package/dist/routes/calendar.js +115 -0
- package/dist/routes/calendar.js.map +1 -0
- package/dist/routes/config.d.ts +9 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +75 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/gcal.d.ts +10 -0
- package/dist/routes/gcal.d.ts.map +1 -0
- package/dist/routes/gcal.js +100 -0
- package/dist/routes/gcal.js.map +1 -0
- package/dist/routes/index.d.ts +8 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +8 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/reports.d.ts +10 -0
- package/dist/routes/reports.d.ts.map +1 -0
- package/dist/routes/reports.js +175 -0
- package/dist/routes/reports.js.map +1 -0
- package/dist/types/index.d.ts +190 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/configValidator.d.ts +43 -0
- package/dist/utils/configValidator.d.ts.map +1 -0
- package/dist/utils/configValidator.js +435 -0
- package/dist/utils/configValidator.js.map +1 -0
- package/dist/utils/fileManager.d.ts +101 -0
- package/dist/utils/fileManager.d.ts.map +1 -0
- package/dist/utils/fileManager.js +295 -0
- package/dist/utils/fileManager.js.map +1 -0
- package/dist/utils/git.d.ts +42 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +130 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/markdown.d.ts +23 -0
- package/dist/utils/markdown.d.ts.map +1 -0
- package/dist/utils/markdown.js +378 -0
- package/dist/utils/markdown.js.map +1 -0
- package/dist/utils/slack.d.ts +24 -0
- package/dist/utils/slack.d.ts.map +1 -0
- package/dist/utils/slack.js +90 -0
- package/dist/utils/slack.js.map +1 -0
- package/dist/utils/validator.d.ts +66 -0
- package/dist/utils/validator.d.ts.map +1 -0
- package/dist/utils/validator.js +359 -0
- package/dist/utils/validator.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown パーサー・ジェネレーター
|
|
3
|
+
*
|
|
4
|
+
* 日報のMarkdown形式を解析・生成する
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Markdownコンテンツをパースして DailyReport オブジェクトに変換
|
|
8
|
+
*/
|
|
9
|
+
export function parseMarkdown(date, content) {
|
|
10
|
+
const report = {
|
|
11
|
+
date,
|
|
12
|
+
author: '',
|
|
13
|
+
plan: [],
|
|
14
|
+
result: [],
|
|
15
|
+
todos: [],
|
|
16
|
+
notes: '',
|
|
17
|
+
};
|
|
18
|
+
const lines = content.split('\n');
|
|
19
|
+
let currentSection = '';
|
|
20
|
+
let currentProject = '';
|
|
21
|
+
const noteLines = [];
|
|
22
|
+
let todoIdCounter = 0;
|
|
23
|
+
let scheduleIdCounter = 0;
|
|
24
|
+
// 終了時刻を保持(セクションごと)
|
|
25
|
+
let planEndTime = '';
|
|
26
|
+
let resultEndTime = '';
|
|
27
|
+
// ヘッダー解析: # [日報] 著者名 日付
|
|
28
|
+
const headerMatch = lines[0]?.match(/^#\s+\[日報\]\s+(.+?)\s+(\d{4}-\d{2}-\d{2})/);
|
|
29
|
+
if (headerMatch) {
|
|
30
|
+
report.author = headerMatch[1];
|
|
31
|
+
}
|
|
32
|
+
for (let i = 0; i < lines.length; i++) {
|
|
33
|
+
const line = lines[i];
|
|
34
|
+
// セクション検出
|
|
35
|
+
if (line.match(/^##\s+\[PLAN\]/i)) {
|
|
36
|
+
currentSection = 'plan';
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (line.match(/^##\s+\[RESULT\]/i)) {
|
|
40
|
+
currentSection = 'result';
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (line.match(/^##\s+\[TODO\]/i)) {
|
|
44
|
+
currentSection = 'todo';
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (line.match(/^##\s+\[NOTE\]/i)) {
|
|
48
|
+
currentSection = 'note';
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
// PLAN/RESULT のパース
|
|
52
|
+
if ((currentSection === 'plan' || currentSection === 'result') && line.startsWith('*')) {
|
|
53
|
+
// 時刻 [プロジェクト] タスク名 形式
|
|
54
|
+
const match = line.match(/^\*\s+(\d{2}:\d{2})\s+\[([^\]]+)\]\s+(.+)$/);
|
|
55
|
+
if (match) {
|
|
56
|
+
const item = {
|
|
57
|
+
id: `${currentSection[0]}${scheduleIdCounter++}`,
|
|
58
|
+
time: match[1],
|
|
59
|
+
project: match[2],
|
|
60
|
+
task: match[3].trim(),
|
|
61
|
+
};
|
|
62
|
+
// メタデータ脚注のパース
|
|
63
|
+
const footnoteMatch = item.task.match(/\[\^([^\]]+)\]$/);
|
|
64
|
+
if (footnoteMatch) {
|
|
65
|
+
item.task = item.task.replace(/\[\^[^\]]+\]$/, '').trim();
|
|
66
|
+
}
|
|
67
|
+
if (currentSection === 'plan') {
|
|
68
|
+
report.plan.push(item);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
report.result.push(item);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// 終了時刻のみの行をチェック(* 17:00 のような形式)
|
|
76
|
+
const endTimeMatch = line.match(/^\*\s+(\d{2}:\d{2})\s*$/);
|
|
77
|
+
if (endTimeMatch) {
|
|
78
|
+
const endTime = endTimeMatch[1];
|
|
79
|
+
const items = currentSection === 'plan' ? report.plan : report.result;
|
|
80
|
+
// 直前のアイテムのdurationを計算(休憩時間の前のアイテム)
|
|
81
|
+
if (items.length > 0) {
|
|
82
|
+
const lastItem = items[items.length - 1];
|
|
83
|
+
if (lastItem.duration === undefined) {
|
|
84
|
+
const startMinutes = timeToMinutes(lastItem.time);
|
|
85
|
+
const endMinutes = timeToMinutes(endTime);
|
|
86
|
+
lastItem.duration = endMinutes - startMinutes;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// 最終終了時刻を更新
|
|
90
|
+
if (currentSection === 'plan') {
|
|
91
|
+
planEndTime = endTime;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
resultEndTime = endTime;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// TODOセクション内のプロジェクトグループ
|
|
100
|
+
if (currentSection === 'todo' && line.match(/^###\s+/)) {
|
|
101
|
+
const projectMatch = line.match(/^###\s+(\S+)/);
|
|
102
|
+
if (projectMatch) {
|
|
103
|
+
currentProject = projectMatch[1];
|
|
104
|
+
}
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
// TODO のパース
|
|
108
|
+
if (currentSection === 'todo' && line.match(/^-\s+\[/)) {
|
|
109
|
+
const todo = parseTodoLine(line, `t${todoIdCounter++}`, currentProject);
|
|
110
|
+
if (todo) {
|
|
111
|
+
// 詳細説明のパース(次の行が2スペースインデント)
|
|
112
|
+
const descLines = [];
|
|
113
|
+
let j = i + 1;
|
|
114
|
+
while (j < lines.length && lines[j].match(/^\s{2}\S/)) {
|
|
115
|
+
descLines.push(lines[j].trim());
|
|
116
|
+
j++;
|
|
117
|
+
}
|
|
118
|
+
if (descLines.length > 0) {
|
|
119
|
+
todo.description = descLines.join('\n');
|
|
120
|
+
}
|
|
121
|
+
report.todos.push(todo);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// NOTE のパース
|
|
125
|
+
if (currentSection === 'note' && !line.startsWith('##')) {
|
|
126
|
+
noteLines.push(line);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
report.notes = noteLines.join('\n').trim();
|
|
130
|
+
// durationを計算(終了時刻を考慮)
|
|
131
|
+
calculateDurationsWithEndTime(report.plan, planEndTime);
|
|
132
|
+
calculateDurationsWithEndTime(report.result, resultEndTime);
|
|
133
|
+
return report;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* TODO行をパース
|
|
137
|
+
*/
|
|
138
|
+
function parseTodoLine(line, id, defaultProject) {
|
|
139
|
+
// - [ステータス] @期日 !!! タスク名 or - [ステータス] @期日 !!! [プロジェクト] タスク名
|
|
140
|
+
const match = line.match(/^-\s+\[([xX\s\*\->])\]\s*(.*)$/);
|
|
141
|
+
if (!match)
|
|
142
|
+
return null;
|
|
143
|
+
const status = parseStatusMark(match[1]);
|
|
144
|
+
let remainder = match[2].trim();
|
|
145
|
+
// 期日パース @YYYY-MM-DD
|
|
146
|
+
let deadline;
|
|
147
|
+
const deadlineMatch = remainder.match(/@(\d{4}-\d{2}-\d{2})\s*/);
|
|
148
|
+
if (deadlineMatch) {
|
|
149
|
+
deadline = deadlineMatch[1];
|
|
150
|
+
remainder = remainder.replace(deadlineMatch[0], '').trim();
|
|
151
|
+
}
|
|
152
|
+
// 優先度パース !!! / !! / !
|
|
153
|
+
let priority;
|
|
154
|
+
if (remainder.startsWith('!!!')) {
|
|
155
|
+
priority = 'high';
|
|
156
|
+
remainder = remainder.slice(3).trim();
|
|
157
|
+
}
|
|
158
|
+
else if (remainder.startsWith('!!')) {
|
|
159
|
+
priority = 'medium';
|
|
160
|
+
remainder = remainder.slice(2).trim();
|
|
161
|
+
}
|
|
162
|
+
else if (remainder.startsWith('!')) {
|
|
163
|
+
priority = 'low';
|
|
164
|
+
remainder = remainder.slice(1).trim();
|
|
165
|
+
}
|
|
166
|
+
// プロジェクトコードパース [P99]
|
|
167
|
+
let project = defaultProject || 'P99';
|
|
168
|
+
const projectMatch = remainder.match(/^\[([^\]]+)\]\s*/);
|
|
169
|
+
if (projectMatch) {
|
|
170
|
+
project = projectMatch[1];
|
|
171
|
+
remainder = remainder.replace(projectMatch[0], '').trim();
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
id,
|
|
175
|
+
project,
|
|
176
|
+
task: remainder,
|
|
177
|
+
status,
|
|
178
|
+
deadline,
|
|
179
|
+
priority,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* ステータスマーク → TodoStatus
|
|
184
|
+
*/
|
|
185
|
+
function parseStatusMark(mark) {
|
|
186
|
+
switch (mark.toLowerCase().trim()) {
|
|
187
|
+
case 'x': return 'completed';
|
|
188
|
+
case '*': return 'in_progress';
|
|
189
|
+
case '-': return 'on_hold';
|
|
190
|
+
case '>': return 'on_hold';
|
|
191
|
+
default: return 'pending';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* TodoStatus → ステータスマーク
|
|
196
|
+
*/
|
|
197
|
+
function getStatusMark(status) {
|
|
198
|
+
switch (status) {
|
|
199
|
+
case 'completed': return 'x';
|
|
200
|
+
case 'in_progress': return '*';
|
|
201
|
+
case 'on_hold': return '-';
|
|
202
|
+
default: return ' ';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* 優先度 → 記号
|
|
207
|
+
*/
|
|
208
|
+
function getPriorityMark(priority) {
|
|
209
|
+
switch (priority) {
|
|
210
|
+
case 'high': return '!!! ';
|
|
211
|
+
case 'medium': return '!! ';
|
|
212
|
+
case 'low': return '! ';
|
|
213
|
+
default: return '';
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* スケジュールアイテムのdurationを計算(終了時刻を考慮)
|
|
218
|
+
* 既にdurationが設定されている場合はスキップ(休憩前のアイテム)
|
|
219
|
+
*/
|
|
220
|
+
function calculateDurationsWithEndTime(items, endTime) {
|
|
221
|
+
for (let i = 0; i < items.length; i++) {
|
|
222
|
+
// 既にdurationが設定されている場合はスキップ(休憩前のアイテムなど)
|
|
223
|
+
if (items[i].duration !== undefined) {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
const startMinutes = timeToMinutes(items[i].time);
|
|
227
|
+
let endMinutes;
|
|
228
|
+
if (i < items.length - 1) {
|
|
229
|
+
// 次のアイテムの開始時刻を終了時刻とする
|
|
230
|
+
endMinutes = timeToMinutes(items[i + 1].time);
|
|
231
|
+
}
|
|
232
|
+
else if (endTime) {
|
|
233
|
+
// 最後のアイテムは終了時刻を使用
|
|
234
|
+
endMinutes = timeToMinutes(endTime);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
// 終了時刻がない場合はスキップ
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
items[i].duration = endMinutes - startMinutes;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* 時刻文字列 → 分
|
|
245
|
+
*/
|
|
246
|
+
function timeToMinutes(time) {
|
|
247
|
+
const [h, m] = time.split(':').map(Number);
|
|
248
|
+
return h * 60 + m;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* 分を加算した時刻文字列を返す
|
|
252
|
+
*/
|
|
253
|
+
function addMinutesToTime(time, minutes) {
|
|
254
|
+
const totalMinutes = timeToMinutes(time) + minutes;
|
|
255
|
+
const h = Math.floor(totalMinutes / 60);
|
|
256
|
+
const m = totalMinutes % 60;
|
|
257
|
+
return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}`;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* スケジュールアイテムをMarkdown行として生成(休憩時間を考慮)
|
|
261
|
+
*/
|
|
262
|
+
function generateScheduleLines(items, lines) {
|
|
263
|
+
for (let i = 0; i < items.length; i++) {
|
|
264
|
+
const item = items[i];
|
|
265
|
+
lines.push(`* ${item.time} [${item.project}] ${item.task}`);
|
|
266
|
+
// 休憩判定: このアイテムの終了時刻と次のアイテムの開始時刻が異なる場合
|
|
267
|
+
if (item.duration !== undefined) {
|
|
268
|
+
const endTime = addMinutesToTime(item.time, item.duration);
|
|
269
|
+
if (i < items.length - 1) {
|
|
270
|
+
const nextItem = items[i + 1];
|
|
271
|
+
// 終了時刻と次の開始時刻が異なる場合、終了時刻行を出力(休憩)
|
|
272
|
+
if (endTime !== nextItem.time) {
|
|
273
|
+
lines.push(`* ${endTime}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
// 最後のアイテムは終了時刻を出力
|
|
278
|
+
lines.push(`* ${endTime}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* DailyReport オブジェクトからMarkdownコンテンツを生成
|
|
285
|
+
*/
|
|
286
|
+
export function generateMarkdown(report) {
|
|
287
|
+
const lines = [];
|
|
288
|
+
lines.push(`# [日報] ${report.author} ${report.date}`);
|
|
289
|
+
lines.push('');
|
|
290
|
+
// PLAN
|
|
291
|
+
lines.push('## [PLAN]');
|
|
292
|
+
lines.push('');
|
|
293
|
+
generateScheduleLines(report.plan, lines);
|
|
294
|
+
lines.push('');
|
|
295
|
+
// RESULT
|
|
296
|
+
lines.push('## [RESULT]');
|
|
297
|
+
lines.push('');
|
|
298
|
+
generateScheduleLines(report.result, lines);
|
|
299
|
+
lines.push('');
|
|
300
|
+
// TODO - プロジェクト別グループ化
|
|
301
|
+
lines.push('## [TODO]');
|
|
302
|
+
lines.push('');
|
|
303
|
+
// プロジェクトごとにグループ化
|
|
304
|
+
const todosByProject = {};
|
|
305
|
+
for (const todo of report.todos) {
|
|
306
|
+
if (!todosByProject[todo.project]) {
|
|
307
|
+
todosByProject[todo.project] = [];
|
|
308
|
+
}
|
|
309
|
+
todosByProject[todo.project].push(todo);
|
|
310
|
+
}
|
|
311
|
+
for (const [project, todos] of Object.entries(todosByProject)) {
|
|
312
|
+
lines.push(`### ${project}`);
|
|
313
|
+
for (const todo of todos) {
|
|
314
|
+
const statusMark = getStatusMark(todo.status);
|
|
315
|
+
const deadlineMark = todo.deadline ? `@${todo.deadline} ` : '';
|
|
316
|
+
const priorityMark = getPriorityMark(todo.priority);
|
|
317
|
+
lines.push(`- [${statusMark}] ${deadlineMark}${priorityMark}${todo.task}`);
|
|
318
|
+
if (todo.description) {
|
|
319
|
+
for (const descLine of todo.description.split('\n')) {
|
|
320
|
+
lines.push(` ${descLine}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
lines.push('');
|
|
326
|
+
// NOTE
|
|
327
|
+
if (report.notes) {
|
|
328
|
+
lines.push('## [NOTE]');
|
|
329
|
+
lines.push('');
|
|
330
|
+
lines.push(report.notes);
|
|
331
|
+
}
|
|
332
|
+
return lines.join('\n');
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* 統計情報を計算
|
|
336
|
+
*/
|
|
337
|
+
export function calculateStats(report) {
|
|
338
|
+
const projectHours = {};
|
|
339
|
+
let planMinutes = 0;
|
|
340
|
+
for (const item of report.plan) {
|
|
341
|
+
planMinutes += item.duration || 0;
|
|
342
|
+
}
|
|
343
|
+
let resultMinutes = 0;
|
|
344
|
+
for (const item of report.result) {
|
|
345
|
+
const duration = item.duration || 0;
|
|
346
|
+
resultMinutes += duration;
|
|
347
|
+
projectHours[item.project] = (projectHours[item.project] || 0) + duration / 60;
|
|
348
|
+
}
|
|
349
|
+
return {
|
|
350
|
+
planHours: planMinutes / 60,
|
|
351
|
+
resultHours: resultMinutes / 60,
|
|
352
|
+
todoCount: report.todos.length,
|
|
353
|
+
todoCompleted: report.todos.filter(t => t.status === 'completed').length,
|
|
354
|
+
todoInProgress: report.todos.filter(t => t.status === 'in_progress').length,
|
|
355
|
+
projectHours,
|
|
356
|
+
updatedAt: new Date().toISOString(),
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* frontmatter付きMarkdownを生成
|
|
361
|
+
*/
|
|
362
|
+
export function generateMarkdownWithFrontmatter(report, stats) {
|
|
363
|
+
const frontmatter = [
|
|
364
|
+
'---',
|
|
365
|
+
`planHours: ${stats.planHours}`,
|
|
366
|
+
`resultHours: ${stats.resultHours}`,
|
|
367
|
+
`todoCount: ${stats.todoCount}`,
|
|
368
|
+
`todoCompleted: ${stats.todoCompleted}`,
|
|
369
|
+
`todoInProgress: ${stats.todoInProgress}`,
|
|
370
|
+
`projectHours:`,
|
|
371
|
+
...Object.entries(stats.projectHours).map(([k, v]) => ` ${k}: ${v}`),
|
|
372
|
+
`updatedAt: ${stats.updatedAt}`,
|
|
373
|
+
'---',
|
|
374
|
+
'',
|
|
375
|
+
];
|
|
376
|
+
return frontmatter.join('\n') + generateMarkdown(report);
|
|
377
|
+
}
|
|
378
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/utils/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slack連携ユーティリティ
|
|
3
|
+
*/
|
|
4
|
+
interface SlackConfig {
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
webhookUrl?: string;
|
|
7
|
+
channel?: string;
|
|
8
|
+
username?: string;
|
|
9
|
+
iconEmoji?: string;
|
|
10
|
+
}
|
|
11
|
+
interface SlackPostResult {
|
|
12
|
+
success: boolean;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Slack設定を取得
|
|
17
|
+
*/
|
|
18
|
+
export declare function getSlackConfig(): SlackConfig | null;
|
|
19
|
+
/**
|
|
20
|
+
* Slackに日報を投稿
|
|
21
|
+
*/
|
|
22
|
+
export declare function postToSlack(date: string, content: string): Promise<SlackPostResult>;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=slack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../../src/utils/slack.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,UAAU,WAAW;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,WAAW,GAAG,IAAI,CAsBnD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA0CzF"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slack連携ユーティリティ
|
|
3
|
+
*/
|
|
4
|
+
import { getRootConfig } from './fileManager.js';
|
|
5
|
+
/**
|
|
6
|
+
* Slack設定を取得
|
|
7
|
+
*/
|
|
8
|
+
export function getSlackConfig() {
|
|
9
|
+
const config = getRootConfig();
|
|
10
|
+
if (!config)
|
|
11
|
+
return null;
|
|
12
|
+
// config.yamlからslack設定を取得
|
|
13
|
+
const slackConfig = config.slack;
|
|
14
|
+
if (!slackConfig || !slackConfig.enabled) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
// 環境変数からWebhook URLを取得(設定ファイルより優先)
|
|
18
|
+
const webhookUrl = process.env.SLACK_WEBHOOK_URL || slackConfig.webhookUrl;
|
|
19
|
+
// ${SLACK_WEBHOOK_URL} のようなプレースホルダーを環境変数で置換
|
|
20
|
+
const resolvedWebhookUrl = webhookUrl?.startsWith('${')
|
|
21
|
+
? process.env.SLACK_WEBHOOK_URL
|
|
22
|
+
: webhookUrl;
|
|
23
|
+
return {
|
|
24
|
+
...slackConfig,
|
|
25
|
+
webhookUrl: resolvedWebhookUrl,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Slackに日報を投稿
|
|
30
|
+
*/
|
|
31
|
+
export async function postToSlack(date, content) {
|
|
32
|
+
const config = getSlackConfig();
|
|
33
|
+
if (!config) {
|
|
34
|
+
return { success: false, error: 'Slack連携が設定されていません' };
|
|
35
|
+
}
|
|
36
|
+
if (!config.webhookUrl) {
|
|
37
|
+
return { success: false, error: 'Slack Webhook URLが設定されていません(環境変数 SLACK_WEBHOOK_URL を設定してください)' };
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
// Markdownから見出しを除去してシンプルなテキストに変換
|
|
41
|
+
const formattedContent = formatForSlack(date, content);
|
|
42
|
+
const payload = {
|
|
43
|
+
text: formattedContent,
|
|
44
|
+
username: config.username || '日報ダッシュボード',
|
|
45
|
+
icon_emoji: config.iconEmoji || ':memo:',
|
|
46
|
+
...(config.channel && { channel: config.channel }),
|
|
47
|
+
};
|
|
48
|
+
const response = await fetch(config.webhookUrl, {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
headers: {
|
|
51
|
+
'Content-Type': 'application/json',
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify(payload),
|
|
54
|
+
});
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
const errorText = await response.text();
|
|
57
|
+
return { success: false, error: `Slack APIエラー: ${response.status} ${errorText}` };
|
|
58
|
+
}
|
|
59
|
+
return { success: true };
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
error: error instanceof Error ? error.message : 'Slack投稿に失敗しました'
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Markdownコンテンツをslack向けにフォーマット
|
|
70
|
+
*/
|
|
71
|
+
function formatForSlack(date, content) {
|
|
72
|
+
// frontmatterを除去
|
|
73
|
+
const contentWithoutFrontmatter = content.replace(/^---[\s\S]*?---\n/, '');
|
|
74
|
+
// Markdown見出しをSlack形式に変換
|
|
75
|
+
let formatted = contentWithoutFrontmatter
|
|
76
|
+
// H1 -> 太字
|
|
77
|
+
.replace(/^# (.+)$/gm, '*$1*')
|
|
78
|
+
// H2 -> 太字
|
|
79
|
+
.replace(/^## (.+)$/gm, '*$1*')
|
|
80
|
+
// H3 -> 太字
|
|
81
|
+
.replace(/^### (.+)$/gm, '*$1*')
|
|
82
|
+
// チェックボックス
|
|
83
|
+
.replace(/^- \[x\]/gm, '✅')
|
|
84
|
+
.replace(/^- \[\*\]/gm, '🔄')
|
|
85
|
+
.replace(/^- \[ \]/gm, '⬜')
|
|
86
|
+
// リスト
|
|
87
|
+
.replace(/^\* /gm, '• ');
|
|
88
|
+
return `📋 *日報 ${date}*\n\n${formatted}`;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=slack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack.js","sourceRoot":"","sources":["../../src/utils/slack.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 日報Markdownフォーマット バリデーター
|
|
3
|
+
*
|
|
4
|
+
* 既存の日報データを仕様に照らし合わせて検証し、
|
|
5
|
+
* 差分を検出・報告する
|
|
6
|
+
*/
|
|
7
|
+
export interface ValidationIssue {
|
|
8
|
+
line: number;
|
|
9
|
+
column?: number;
|
|
10
|
+
severity: 'error' | 'warning' | 'info';
|
|
11
|
+
code: string;
|
|
12
|
+
message: string;
|
|
13
|
+
suggestion?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ValidationResult {
|
|
16
|
+
file: string;
|
|
17
|
+
date: string;
|
|
18
|
+
isValid: boolean;
|
|
19
|
+
issues: ValidationIssue[];
|
|
20
|
+
summary: {
|
|
21
|
+
errors: number;
|
|
22
|
+
warnings: number;
|
|
23
|
+
infos: number;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface ValidatorOptions {
|
|
27
|
+
/** 厳格モード: warningもエラーとして扱う */
|
|
28
|
+
strict?: boolean;
|
|
29
|
+
/** 検証をスキップするルール */
|
|
30
|
+
skipRules?: string[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 日報Markdownをバリデート
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateReport(content: string, filePath: string, options?: ValidatorOptions): ValidationResult;
|
|
36
|
+
/**
|
|
37
|
+
* バリデーション結果をフォーマットして出力用文字列を生成
|
|
38
|
+
*/
|
|
39
|
+
export declare function formatValidationResult(result: ValidationResult, options?: {
|
|
40
|
+
color?: boolean;
|
|
41
|
+
verbose?: boolean;
|
|
42
|
+
}): string;
|
|
43
|
+
/**
|
|
44
|
+
* 複数のバリデーション結果をサマリー出力
|
|
45
|
+
*/
|
|
46
|
+
export declare function formatValidationSummary(results: ValidationResult[], options?: {
|
|
47
|
+
color?: boolean;
|
|
48
|
+
}): string;
|
|
49
|
+
/**
|
|
50
|
+
* バリデーションルール一覧
|
|
51
|
+
*/
|
|
52
|
+
export declare const VALIDATION_RULES: {
|
|
53
|
+
readonly 'header-format': "日報ヘッダーの形式チェック";
|
|
54
|
+
readonly 'separator-line': "セクション区切り線(=====)の検出";
|
|
55
|
+
readonly 'location-subsection': "場所サブセクション(### [home])の検出";
|
|
56
|
+
readonly 'schedule-item-format': "PLAN/RESULT項目の形式チェック";
|
|
57
|
+
readonly 'time-format': "時刻形式のチェック";
|
|
58
|
+
readonly 'todo-list-marker': "TODOリストマーカーの統一チェック";
|
|
59
|
+
readonly 'todo-inline-project': "TODO行内のプロジェクトコード検出";
|
|
60
|
+
readonly 'todo-deadline-format': "期限の括弧形式検出";
|
|
61
|
+
readonly 'nested-todo': "ネストされたTODO検出";
|
|
62
|
+
readonly 'project-only-line': "プロジェクト名のみの行検出";
|
|
63
|
+
readonly 'required-sections': "必須セクションの存在チェック";
|
|
64
|
+
};
|
|
65
|
+
export type ValidationRuleCode = keyof typeof VALIDATION_RULES;
|
|
66
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/utils/validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B,8BAA8B;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mBAAmB;IACnB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,gBAAgB,CAqQlB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GACnD,MAAM,CA+DR;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,gBAAgB,EAAE,EAC3B,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAChC,MAAM,CA8BR;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;CAYnB,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAAG,MAAM,OAAO,gBAAgB,CAAC"}
|