@md2do/cli 0.3.0 → 0.4.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.
Files changed (34) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/coverage/coverage-final.json +2 -2
  3. package/coverage/index.html +7 -7
  4. package/coverage/lcov-report/index.html +7 -7
  5. package/coverage/lcov-report/src/cli.ts.html +1 -1
  6. package/coverage/lcov-report/src/commands/index.html +5 -5
  7. package/coverage/lcov-report/src/commands/index.ts.html +1 -1
  8. package/coverage/lcov-report/src/commands/list.ts.html +103 -22
  9. package/coverage/lcov-report/src/commands/stats.ts.html +1 -1
  10. package/coverage/lcov-report/src/commands/todoist.ts.html +1 -1
  11. package/coverage/lcov-report/src/formatters/index.html +1 -1
  12. package/coverage/lcov-report/src/formatters/json.ts.html +1 -1
  13. package/coverage/lcov-report/src/formatters/pretty.ts.html +1 -1
  14. package/coverage/lcov-report/src/index.html +5 -5
  15. package/coverage/lcov-report/src/index.ts.html +1 -1
  16. package/coverage/lcov-report/src/scanner.ts.html +87 -6
  17. package/coverage/lcov.info +56 -2
  18. package/coverage/src/cli.ts.html +1 -1
  19. package/coverage/src/commands/index.html +5 -5
  20. package/coverage/src/commands/index.ts.html +1 -1
  21. package/coverage/src/commands/list.ts.html +103 -22
  22. package/coverage/src/commands/stats.ts.html +1 -1
  23. package/coverage/src/commands/todoist.ts.html +1 -1
  24. package/coverage/src/formatters/index.html +1 -1
  25. package/coverage/src/formatters/json.ts.html +1 -1
  26. package/coverage/src/formatters/pretty.ts.html +1 -1
  27. package/coverage/src/index.html +5 -5
  28. package/coverage/src/index.ts.html +1 -1
  29. package/coverage/src/scanner.ts.html +87 -6
  30. package/dist/cli.js +22 -6
  31. package/dist/index.js +22 -6
  32. package/package.json +5 -5
  33. package/src/commands/list.ts +16 -5
  34. package/src/scanner.ts +23 -1
@@ -25,7 +25,7 @@
25
25
  <div class='fl pad1y space-right2'>
26
26
  <span class="strong">0% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>0/105</span>
28
+ <span class='fraction'>0/132</span>
29
29
  </div>
30
30
 
31
31
 
@@ -46,7 +46,7 @@
46
46
  <div class='fl pad1y space-right2'>
47
47
  <span class="strong">0% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>0/105</span>
49
+ <span class='fraction'>0/132</span>
50
50
  </div>
51
51
 
52
52
 
@@ -168,7 +168,61 @@
168
168
  <a name='L103'></a><a href='#L103'>103</a>
169
169
  <a name='L104'></a><a href='#L104'>104</a>
170
170
  <a name='L105'></a><a href='#L105'>105</a>
171
- <a name='L106'></a><a href='#L106'>106</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
199
+ <span class="cline-any cline-no">&nbsp;</span>
200
+ <span class="cline-any cline-no">&nbsp;</span>
201
+ <span class="cline-any cline-no">&nbsp;</span>
202
+ <span class="cline-any cline-no">&nbsp;</span>
203
+ <span class="cline-any cline-no">&nbsp;</span>
204
+ <span class="cline-any cline-no">&nbsp;</span>
205
+ <span class="cline-any cline-no">&nbsp;</span>
206
+ <span class="cline-any cline-no">&nbsp;</span>
207
+ <span class="cline-any cline-no">&nbsp;</span>
208
+ <span class="cline-any cline-no">&nbsp;</span>
209
+ <span class="cline-any cline-no">&nbsp;</span>
210
+ <span class="cline-any cline-no">&nbsp;</span>
211
+ <span class="cline-any cline-no">&nbsp;</span>
212
+ <span class="cline-any cline-no">&nbsp;</span>
213
+ <span class="cline-any cline-no">&nbsp;</span>
214
+ <span class="cline-any cline-no">&nbsp;</span>
215
+ <span class="cline-any cline-no">&nbsp;</span>
216
+ <span class="cline-any cline-no">&nbsp;</span>
217
+ <span class="cline-any cline-no">&nbsp;</span>
218
+ <span class="cline-any cline-no">&nbsp;</span>
219
+ <span class="cline-any cline-no">&nbsp;</span>
220
+ <span class="cline-any cline-no">&nbsp;</span>
221
+ <span class="cline-any cline-no">&nbsp;</span>
222
+ <span class="cline-any cline-no">&nbsp;</span>
223
+ <span class="cline-any cline-no">&nbsp;</span>
224
+ <span class="cline-any cline-no">&nbsp;</span>
225
+ <span class="cline-any cline-no">&nbsp;</span>
172
226
  <span class="cline-any cline-no">&nbsp;</span>
173
227
  <span class="cline-any cline-no">&nbsp;</span>
174
228
  <span class="cline-any cline-no">&nbsp;</span>
@@ -297,6 +351,21 @@
297
351
  <span class="cstat-no" title="statement not covered" > * Whether to follow symbolic links (defaults to false)</span>
298
352
  <span class="cstat-no" title="statement not covered" > */</span>
299
353
  <span class="cstat-no" title="statement not covered" > followSymlinks?: boolean;</span>
354
+ <span class="cstat-no" title="statement not covered" ></span>
355
+ <span class="cstat-no" title="statement not covered" > /**</span>
356
+ <span class="cstat-no" title="statement not covered" > * Workday start time for default due times (e.g., "08:00")</span>
357
+ <span class="cstat-no" title="statement not covered" > */</span>
358
+ <span class="cstat-no" title="statement not covered" > workdayStartTime?: string;</span>
359
+ <span class="cstat-no" title="statement not covered" ></span>
360
+ <span class="cstat-no" title="statement not covered" > /**</span>
361
+ <span class="cstat-no" title="statement not covered" > * Workday end time for default due times (e.g., "17:00")</span>
362
+ <span class="cstat-no" title="statement not covered" > */</span>
363
+ <span class="cstat-no" title="statement not covered" > workdayEndTime?: string;</span>
364
+ <span class="cstat-no" title="statement not covered" ></span>
365
+ <span class="cstat-no" title="statement not covered" > /**</span>
366
+ <span class="cstat-no" title="statement not covered" > * Default due time to use when no time is specified ("start" or "end")</span>
367
+ <span class="cstat-no" title="statement not covered" > */</span>
368
+ <span class="cstat-no" title="statement not covered" > defaultDueTime?: 'start' | 'end';</span>
300
369
  <span class="cstat-no" title="statement not covered" >}</span>
301
370
  <span class="cstat-no" title="statement not covered" ></span>
302
371
  <span class="cstat-no" title="statement not covered" >export interface ScanResult {</span>
@@ -331,6 +400,9 @@
331
400
  <span class="cstat-no" title="statement not covered" > '**/.next/**',</span>
332
401
  <span class="cstat-no" title="statement not covered" > ],</span>
333
402
  <span class="cstat-no" title="statement not covered" > followSymlinks = false,</span>
403
+ <span class="cstat-no" title="statement not covered" > workdayStartTime,</span>
404
+ <span class="cstat-no" title="statement not covered" > workdayEndTime,</span>
405
+ <span class="cstat-no" title="statement not covered" > defaultDueTime,</span>
334
406
  <span class="cstat-no" title="statement not covered" > } = options;</span>
335
407
  <span class="cstat-no" title="statement not covered" ></span>
336
408
  <span class="cstat-no" title="statement not covered" > // Find all markdown files</span>
@@ -352,16 +424,25 @@
352
424
  <span class="cstat-no" title="statement not covered" > const fullPath = `${root}/${file}`;</span>
353
425
  <span class="cstat-no" title="statement not covered" > const content = await readFile(fullPath, 'utf-8');</span>
354
426
  <span class="cstat-no" title="statement not covered" ></span>
355
- <span class="cstat-no" title="statement not covered" > const result = scanner.scanFile(file, content);</span>
427
+ <span class="cstat-no" title="statement not covered" > const result = scanner.scanFile(file, content, {</span>
428
+ <span class="cstat-no" title="statement not covered" > ...(workdayStartTime &amp;&amp; { workdayStartTime }),</span>
429
+ <span class="cstat-no" title="statement not covered" > ...(workdayEndTime &amp;&amp; { workdayEndTime }),</span>
430
+ <span class="cstat-no" title="statement not covered" > ...(defaultDueTime &amp;&amp; { defaultDueTime }),</span>
431
+ <span class="cstat-no" title="statement not covered" > });</span>
356
432
  <span class="cstat-no" title="statement not covered" > allTasks.push(...result.tasks);</span>
357
433
  <span class="cstat-no" title="statement not covered" > allWarnings.push(...result.warnings);</span>
358
434
  <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
359
435
  <span class="cstat-no" title="statement not covered" > // Add warning for files that couldn't be read</span>
436
+ <span class="cstat-no" title="statement not covered" > const message = `Failed to read file: ${error instanceof Error ? error.message : 'Unknown error'}`;</span>
360
437
  <span class="cstat-no" title="statement not covered" > allWarnings.push({</span>
438
+ <span class="cstat-no" title="statement not covered" > severity: 'error',</span>
439
+ <span class="cstat-no" title="statement not covered" > source: 'md2do',</span>
440
+ <span class="cstat-no" title="statement not covered" > ruleId: 'file-read-error',</span>
361
441
  <span class="cstat-no" title="statement not covered" > file,</span>
362
442
  <span class="cstat-no" title="statement not covered" > line: 0,</span>
363
443
  <span class="cstat-no" title="statement not covered" > text: '',</span>
364
- <span class="cstat-no" title="statement not covered" > reason: `Failed to read file: ${error instanceof Error ? error.message : 'Unknown error'}`,</span>
444
+ <span class="cstat-no" title="statement not covered" > message,</span>
445
+ <span class="cstat-no" title="statement not covered" > reason: message,</span>
365
446
  <span class="cstat-no" title="statement not covered" > });</span>
366
447
  <span class="cstat-no" title="statement not covered" > }</span>
367
448
  <span class="cstat-no" title="statement not covered" > }</span>
@@ -385,7 +466,7 @@
385
466
  <div class='footer quiet pad2 space-top1 center small'>
386
467
  Code coverage generated by
387
468
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
388
- at 2026-01-26T03:50:54.693Z
469
+ at 2026-02-05T05:58:17.761Z
389
470
  </div>
390
471
  <script src="../prettify.js"></script>
391
472
  <script>
package/dist/cli.js CHANGED
@@ -49,7 +49,10 @@ async function scanMarkdownFiles(options = {}) {
49
49
  "**/build/**",
50
50
  "**/.next/**"
51
51
  ],
52
- followSymlinks = false
52
+ followSymlinks = false,
53
+ workdayStartTime,
54
+ workdayEndTime,
55
+ defaultDueTime
53
56
  } = options;
54
57
  const files = await (0, import_fast_glob.default)(pattern, {
55
58
  cwd: root,
@@ -65,7 +68,11 @@ async function scanMarkdownFiles(options = {}) {
65
68
  try {
66
69
  const fullPath = `${root}/${file}`;
67
70
  const content = await (0, import_promises.readFile)(fullPath, "utf-8");
68
- const result = scanner.scanFile(file, content);
71
+ const result = scanner.scanFile(file, content, {
72
+ ...workdayStartTime && { workdayStartTime },
73
+ ...workdayEndTime && { workdayEndTime },
74
+ ...defaultDueTime && { defaultDueTime }
75
+ });
69
76
  allTasks.push(...result.tasks);
70
77
  allWarnings.push(...result.warnings);
71
78
  } catch (error) {
@@ -299,10 +306,22 @@ function createListCommand() {
299
306
  "pretty"
300
307
  ).option("--no-colors", "Disable colors in output").option("--no-paths", "Hide file paths").option("--context", "Show context information (project, person, heading)").option("--no-warnings", "Hide all warnings").option("--all-warnings", "Show all warnings (default shows first 5)").action(async (options) => {
301
308
  try {
309
+ const config = await (0, import_config.loadConfig)({
310
+ cwd: options.path || process.cwd()
311
+ });
302
312
  const scanResult = await scanMarkdownFiles({
303
313
  root: options.path || process.cwd(),
304
314
  ...options.pattern !== void 0 && { pattern: options.pattern },
305
- ...options.exclude !== void 0 && { exclude: options.exclude }
315
+ ...options.exclude !== void 0 && { exclude: options.exclude },
316
+ ...config.workday?.startTime && {
317
+ workdayStartTime: config.workday.startTime
318
+ },
319
+ ...config.workday?.endTime && {
320
+ workdayEndTime: config.workday.endTime
321
+ },
322
+ ...config.workday?.defaultDueTime && {
323
+ defaultDueTime: config.workday.defaultDueTime
324
+ }
306
325
  });
307
326
  let tasks = scanResult.tasks;
308
327
  const taskFilters = [];
@@ -395,9 +414,6 @@ function createListCommand() {
395
414
  }
396
415
  console.log(output);
397
416
  if (options.warnings !== false) {
398
- const config = await (0, import_config.loadConfig)({
399
- cwd: options.path || process.cwd()
400
- });
401
417
  const warningConfig = config.warnings ?? import_config.DEFAULT_CONFIG.warnings;
402
418
  const filteredWarnings = (0, import_core2.filterWarnings)(
403
419
  scanResult.warnings,
package/dist/index.js CHANGED
@@ -57,7 +57,10 @@ async function scanMarkdownFiles(options = {}) {
57
57
  "**/build/**",
58
58
  "**/.next/**"
59
59
  ],
60
- followSymlinks = false
60
+ followSymlinks = false,
61
+ workdayStartTime,
62
+ workdayEndTime,
63
+ defaultDueTime
61
64
  } = options;
62
65
  const files = await (0, import_fast_glob.default)(pattern, {
63
66
  cwd: root,
@@ -73,7 +76,11 @@ async function scanMarkdownFiles(options = {}) {
73
76
  try {
74
77
  const fullPath = `${root}/${file}`;
75
78
  const content = await (0, import_promises.readFile)(fullPath, "utf-8");
76
- const result = scanner.scanFile(file, content);
79
+ const result = scanner.scanFile(file, content, {
80
+ ...workdayStartTime && { workdayStartTime },
81
+ ...workdayEndTime && { workdayEndTime },
82
+ ...defaultDueTime && { defaultDueTime }
83
+ });
77
84
  allTasks.push(...result.tasks);
78
85
  allWarnings.push(...result.warnings);
79
86
  } catch (error) {
@@ -307,10 +314,22 @@ function createListCommand() {
307
314
  "pretty"
308
315
  ).option("--no-colors", "Disable colors in output").option("--no-paths", "Hide file paths").option("--context", "Show context information (project, person, heading)").option("--no-warnings", "Hide all warnings").option("--all-warnings", "Show all warnings (default shows first 5)").action(async (options) => {
309
316
  try {
317
+ const config = await (0, import_config.loadConfig)({
318
+ cwd: options.path || process.cwd()
319
+ });
310
320
  const scanResult = await scanMarkdownFiles({
311
321
  root: options.path || process.cwd(),
312
322
  ...options.pattern !== void 0 && { pattern: options.pattern },
313
- ...options.exclude !== void 0 && { exclude: options.exclude }
323
+ ...options.exclude !== void 0 && { exclude: options.exclude },
324
+ ...config.workday?.startTime && {
325
+ workdayStartTime: config.workday.startTime
326
+ },
327
+ ...config.workday?.endTime && {
328
+ workdayEndTime: config.workday.endTime
329
+ },
330
+ ...config.workday?.defaultDueTime && {
331
+ defaultDueTime: config.workday.defaultDueTime
332
+ }
314
333
  });
315
334
  let tasks = scanResult.tasks;
316
335
  const taskFilters = [];
@@ -403,9 +422,6 @@ function createListCommand() {
403
422
  }
404
423
  console.log(output);
405
424
  if (options.warnings !== false) {
406
- const config = await (0, import_config.loadConfig)({
407
- cwd: options.path || process.cwd()
408
- });
409
425
  const warningConfig = config.warnings ?? import_config.DEFAULT_CONFIG.warnings;
410
426
  const filteredWarnings = (0, import_core2.filterWarnings)(
411
427
  scanResult.warnings,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@md2do/cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "CLI interface for md2do task manager",
5
5
  "keywords": [
6
6
  "markdown",
@@ -40,16 +40,16 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@doist/todoist-api-typescript": "^3.0.3",
43
- "chalk": "^4.1.2",
43
+ "chalk": "4.1.2",
44
44
  "cli-table3": "^0.6.5",
45
45
  "commander": "^11.1.0",
46
46
  "cosmiconfig": "^9.0.0",
47
47
  "date-fns": "^3.0.6",
48
48
  "fast-glob": "^3.3.3",
49
49
  "zod": "^3.22.4",
50
- "@md2do/core": "0.3.0",
51
- "@md2do/config": "0.3.0",
52
- "@md2do/todoist": "0.3.0"
50
+ "@md2do/config": "0.4.0",
51
+ "@md2do/core": "0.4.0",
52
+ "@md2do/todoist": "0.4.0"
53
53
  },
54
54
  "devDependencies": {
55
55
  "tsup": "^8.0.1"
@@ -86,11 +86,25 @@ export function createListCommand(): Command {
86
86
 
87
87
  .action(async (options: ListCommandOptions) => {
88
88
  try {
89
- // Scan markdown files
89
+ // Load config first to get workday settings
90
+ const config = await loadConfig({
91
+ cwd: options.path || process.cwd(),
92
+ });
93
+
94
+ // Scan markdown files with workday config
90
95
  const scanResult = await scanMarkdownFiles({
91
96
  root: options.path || process.cwd(),
92
97
  ...(options.pattern !== undefined && { pattern: options.pattern }),
93
98
  ...(options.exclude !== undefined && { exclude: options.exclude }),
99
+ ...(config.workday?.startTime && {
100
+ workdayStartTime: config.workday.startTime,
101
+ }),
102
+ ...(config.workday?.endTime && {
103
+ workdayEndTime: config.workday.endTime,
104
+ }),
105
+ ...(config.workday?.defaultDueTime && {
106
+ defaultDueTime: config.workday.defaultDueTime,
107
+ }),
94
108
  });
95
109
 
96
110
  let tasks = scanResult.tasks;
@@ -212,11 +226,8 @@ export function createListCommand(): Command {
212
226
 
213
227
  console.log(output);
214
228
 
215
- // Load config and apply warning filters (unless --no-warnings overrides)
229
+ // Apply warning filters (unless --no-warnings overrides)
216
230
  if (options.warnings !== false) {
217
- const config = await loadConfig({
218
- cwd: options.path || process.cwd(),
219
- });
220
231
  const warningConfig = config.warnings ?? DEFAULT_CONFIG.warnings;
221
232
 
222
233
  // Apply config-based filtering
package/src/scanner.ts CHANGED
@@ -22,6 +22,21 @@ export interface ScanOptions {
22
22
  * Whether to follow symbolic links (defaults to false)
23
23
  */
24
24
  followSymlinks?: boolean;
25
+
26
+ /**
27
+ * Workday start time for default due times (e.g., "08:00")
28
+ */
29
+ workdayStartTime?: string;
30
+
31
+ /**
32
+ * Workday end time for default due times (e.g., "17:00")
33
+ */
34
+ workdayEndTime?: string;
35
+
36
+ /**
37
+ * Default due time to use when no time is specified ("start" or "end")
38
+ */
39
+ defaultDueTime?: 'start' | 'end';
25
40
  }
26
41
 
27
42
  export interface ScanResult {
@@ -56,6 +71,9 @@ export async function scanMarkdownFiles(
56
71
  '**/.next/**',
57
72
  ],
58
73
  followSymlinks = false,
74
+ workdayStartTime,
75
+ workdayEndTime,
76
+ defaultDueTime,
59
77
  } = options;
60
78
 
61
79
  // Find all markdown files
@@ -77,7 +95,11 @@ export async function scanMarkdownFiles(
77
95
  const fullPath = `${root}/${file}`;
78
96
  const content = await readFile(fullPath, 'utf-8');
79
97
 
80
- const result = scanner.scanFile(file, content);
98
+ const result = scanner.scanFile(file, content, {
99
+ ...(workdayStartTime && { workdayStartTime }),
100
+ ...(workdayEndTime && { workdayEndTime }),
101
+ ...(defaultDueTime && { defaultDueTime }),
102
+ });
81
103
  allTasks.push(...result.tasks);
82
104
  allWarnings.push(...result.warnings);
83
105
  } catch (error) {