@md2do/core 0.2.3 → 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 (53) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/coverage/coverage-final.json +6 -5
  3. package/coverage/index.html +52 -37
  4. package/coverage/lcov-report/index.html +52 -37
  5. package/coverage/lcov-report/src/filters/index.html +1 -1
  6. package/coverage/lcov-report/src/filters/index.ts.html +1 -1
  7. package/coverage/lcov-report/src/index.html +5 -5
  8. package/coverage/lcov-report/src/index.ts.html +13 -4
  9. package/coverage/lcov-report/src/parser/index.html +17 -17
  10. package/coverage/lcov-report/src/parser/index.ts.html +181 -13
  11. package/coverage/lcov-report/src/parser/patterns.ts.html +18 -9
  12. package/coverage/lcov-report/src/scanner/index.html +15 -15
  13. package/coverage/lcov-report/src/scanner/index.ts.html +83 -8
  14. package/coverage/lcov-report/src/sorting/index.html +1 -1
  15. package/coverage/lcov-report/src/sorting/index.ts.html +1 -1
  16. package/coverage/lcov-report/src/utils/dates.ts.html +169 -25
  17. package/coverage/lcov-report/src/utils/id.ts.html +1 -1
  18. package/coverage/lcov-report/src/utils/index.html +19 -19
  19. package/coverage/lcov-report/src/warnings/filter.ts.html +364 -0
  20. package/coverage/lcov-report/src/warnings/index.html +116 -0
  21. package/coverage/lcov-report/src/writer/index.html +1 -1
  22. package/coverage/lcov-report/src/writer/index.ts.html +1 -1
  23. package/coverage/lcov.info +760 -512
  24. package/coverage/src/filters/index.html +1 -1
  25. package/coverage/src/filters/index.ts.html +1 -1
  26. package/coverage/src/index.html +5 -5
  27. package/coverage/src/index.ts.html +13 -4
  28. package/coverage/src/parser/index.html +17 -17
  29. package/coverage/src/parser/index.ts.html +181 -13
  30. package/coverage/src/parser/patterns.ts.html +18 -9
  31. package/coverage/src/scanner/index.html +15 -15
  32. package/coverage/src/scanner/index.ts.html +83 -8
  33. package/coverage/src/sorting/index.html +1 -1
  34. package/coverage/src/sorting/index.ts.html +1 -1
  35. package/coverage/src/utils/dates.ts.html +169 -25
  36. package/coverage/src/utils/id.ts.html +1 -1
  37. package/coverage/src/utils/index.html +19 -19
  38. package/coverage/src/warnings/filter.ts.html +364 -0
  39. package/coverage/src/warnings/index.html +116 -0
  40. package/coverage/src/writer/index.html +1 -1
  41. package/coverage/src/writer/index.ts.html +1 -1
  42. package/dist/index.d.mts +103 -12
  43. package/dist/index.d.ts +103 -12
  44. package/dist/index.js +125 -11
  45. package/dist/index.mjs +125 -12
  46. package/package.json +1 -1
  47. package/src/index.ts +3 -0
  48. package/src/parser/index.ts +61 -5
  49. package/src/parser/patterns.ts +8 -5
  50. package/src/scanner/index.ts +25 -0
  51. package/src/types/index.ts +35 -2
  52. package/src/utils/dates.ts +58 -10
  53. package/src/warnings/filter.ts +93 -0
@@ -5,11 +5,41 @@ import {
5
5
  addWeeks,
6
6
  addMonths,
7
7
  startOfWeek,
8
+ setHours,
9
+ setMinutes,
8
10
  } from 'date-fns';
9
11
  import { PATTERNS } from '../parser/patterns.js';
10
12
 
11
13
  /**
12
- * Parse an absolute date string in various formats
14
+ * Parse a time string in HH:MM or H:MM format
15
+ *
16
+ * @param timeStr - Time string to parse (e.g., "17:00", "9:00")
17
+ * @returns Object with hours and minutes, or null if invalid
18
+ *
19
+ * @example
20
+ * parseTime("17:00") // => { hours: 17, minutes: 0 }
21
+ * parseTime("9:30") // => { hours: 9, minutes: 30 }
22
+ * parseTime("25:00") // => null (invalid hour)
23
+ */
24
+ export function parseTime(
25
+ timeStr: string,
26
+ ): { hours: number; minutes: number } | null {
27
+ const match = timeStr.match(/^(\d{1,2}):(\d{2})$/);
28
+ if (!match || !match[1] || !match[2]) return null;
29
+
30
+ const hours = parseInt(match[1], 10);
31
+ const minutes = parseInt(match[2], 10);
32
+
33
+ // Validate ranges
34
+ if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) {
35
+ return null;
36
+ }
37
+
38
+ return { hours, minutes };
39
+ }
40
+
41
+ /**
42
+ * Parse an absolute date string in various formats, with optional time
13
43
  *
14
44
  * Supported formats:
15
45
  * - ISO: 2026-01-25
@@ -17,24 +47,42 @@ import { PATTERNS } from '../parser/patterns.js';
17
47
  * - US full: 1/25/2026
18
48
  *
19
49
  * @param dateStr - Date string to parse
50
+ * @param timeStr - Optional time string in HH:MM or H:MM format
20
51
  * @returns Parsed Date object or null if invalid
52
+ *
53
+ * @example
54
+ * parseAbsoluteDate("2026-01-25") // => Date at midnight
55
+ * parseAbsoluteDate("2026-01-25", "17:00") // => Date at 5 PM
21
56
  */
22
- export function parseAbsoluteDate(dateStr: string): Date | null {
57
+ export function parseAbsoluteDate(
58
+ dateStr: string,
59
+ timeStr?: string,
60
+ ): Date | null {
23
61
  const referenceDate = new Date();
24
62
 
25
63
  // Try ISO format: 2026-01-25
26
64
  let date = parse(dateStr, 'yyyy-MM-dd', referenceDate);
27
- if (isValid(date)) return date;
65
+ if (!isValid(date)) {
66
+ // Try US short format with 2-digit year: 1/25/26
67
+ date = parse(dateStr, 'M/d/yy', referenceDate);
68
+ }
69
+ if (!isValid(date)) {
70
+ // Try US full format: 1/25/2026
71
+ date = parse(dateStr, 'M/d/yyyy', referenceDate);
72
+ }
28
73
 
29
- // Try US short format with 2-digit year: 1/25/26
30
- date = parse(dateStr, 'M/d/yy', referenceDate);
31
- if (isValid(date)) return date;
74
+ if (!isValid(date)) return null;
32
75
 
33
- // Try US full format: 1/25/2026
34
- date = parse(dateStr, 'M/d/yyyy', referenceDate);
35
- if (isValid(date)) return date;
76
+ // Apply time if provided
77
+ if (timeStr) {
78
+ const time = parseTime(timeStr);
79
+ if (time) {
80
+ date = setHours(date, time.hours);
81
+ date = setMinutes(date, time.minutes);
82
+ }
83
+ }
36
84
 
37
- return null;
85
+ return date;
38
86
  }
39
87
 
40
88
  /**
@@ -0,0 +1,93 @@
1
+ import type { Warning } from '../types/index.js';
2
+
3
+ export interface WarningFilterConfig {
4
+ enabled?: boolean | undefined;
5
+ rules?: Record<string, 'error' | 'warn' | 'info' | 'off'> | undefined;
6
+ }
7
+
8
+ /**
9
+ * Filter warnings based on configuration rules
10
+ *
11
+ * This function applies warning configuration rules to filter out disabled warnings
12
+ * and optionally all warnings if globally disabled.
13
+ *
14
+ * @param warnings - Array of warnings to filter
15
+ * @param config - Warning configuration with enabled flag and rule overrides
16
+ * @returns Filtered array of warnings
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const config = {
21
+ * enabled: true,
22
+ * rules: {
23
+ * 'missing-due-date': 'off',
24
+ * 'duplicate-todoist-id': 'error',
25
+ * },
26
+ * };
27
+ *
28
+ * const filtered = filterWarnings(allWarnings, config);
29
+ * // Returns warnings except those with ruleId 'missing-due-date'
30
+ * ```
31
+ */
32
+ export function filterWarnings(
33
+ warnings: Warning[],
34
+ config: WarningFilterConfig = {},
35
+ ): Warning[] {
36
+ // If warnings are globally disabled, return empty array
37
+ if (config.enabled === false) {
38
+ return [];
39
+ }
40
+
41
+ // If no rules specified, return all warnings
42
+ if (!config.rules) {
43
+ return warnings;
44
+ }
45
+
46
+ // Filter based on rule configuration
47
+ return warnings.filter((warning) => {
48
+ const level = config.rules?.[warning.ruleId];
49
+
50
+ // If rule is not configured, include the warning (default: show)
51
+ if (level === undefined) {
52
+ return true;
53
+ }
54
+
55
+ // Exclude if rule is set to 'off'
56
+ return level !== 'off';
57
+ });
58
+ }
59
+
60
+ /**
61
+ * Group warnings by severity
62
+ *
63
+ * Useful for displaying warnings in order of importance or
64
+ * treating errors differently from warnings.
65
+ *
66
+ * @param warnings - Array of warnings to group
67
+ * @returns Object with warnings grouped by severity level
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * const grouped = groupWarningsBySeverity(warnings);
72
+ * console.log(`${grouped.error.length} errors`);
73
+ * console.log(`${grouped.warning.length} warnings`);
74
+ * console.log(`${grouped.info.length} info messages`);
75
+ * ```
76
+ */
77
+ export function groupWarningsBySeverity(warnings: Warning[]): {
78
+ error: Warning[];
79
+ warning: Warning[];
80
+ info: Warning[];
81
+ } {
82
+ return warnings.reduce(
83
+ (acc, warning) => {
84
+ acc[warning.severity].push(warning);
85
+ return acc;
86
+ },
87
+ { error: [], warning: [], info: [] } as {
88
+ error: Warning[];
89
+ warning: Warning[];
90
+ info: Warning[];
91
+ },
92
+ );
93
+ }