@real1ty-obsidian-plugins/utils 2.2.3 → 2.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 (152) hide show
  1. package/README.md +29 -9
  2. package/dist/{async-utils.d.ts → async/async.d.ts} +1 -1
  3. package/dist/async/async.d.ts.map +1 -0
  4. package/dist/{async-utils.js → async/async.js} +1 -1
  5. package/dist/async/async.js.map +1 -0
  6. package/dist/async/batch-operations.d.ts.map +1 -0
  7. package/dist/async/batch-operations.js.map +1 -0
  8. package/dist/async/index.d.ts +3 -0
  9. package/dist/async/index.d.ts.map +1 -0
  10. package/dist/async/index.js +3 -0
  11. package/dist/async/index.js.map +1 -0
  12. package/dist/core/evaluator-base.d.ts.map +1 -0
  13. package/dist/core/evaluator-base.js.map +1 -0
  14. package/dist/core/generate.d.ts.map +1 -0
  15. package/dist/core/generate.js.map +1 -0
  16. package/dist/core/index.d.ts +3 -0
  17. package/dist/core/index.d.ts.map +1 -0
  18. package/dist/core/index.js +3 -0
  19. package/dist/core/index.js.map +1 -0
  20. package/dist/{date-recurrence-utils.d.ts → date/date-recurrence.d.ts} +1 -1
  21. package/dist/date/date-recurrence.d.ts.map +1 -0
  22. package/dist/{date-recurrence-utils.js → date/date-recurrence.js} +1 -1
  23. package/dist/date/date-recurrence.js.map +1 -0
  24. package/dist/{date-utils.d.ts → date/date.d.ts} +1 -1
  25. package/dist/date/date.d.ts.map +1 -0
  26. package/dist/{date-utils.js → date/date.js} +1 -1
  27. package/dist/date/date.js.map +1 -0
  28. package/dist/date/index.d.ts +3 -0
  29. package/dist/date/index.d.ts.map +1 -0
  30. package/dist/date/index.js +3 -0
  31. package/dist/date/index.js.map +1 -0
  32. package/dist/{child-reference-utils.d.ts → file/child-reference.d.ts} +1 -1
  33. package/dist/file/child-reference.d.ts.map +1 -0
  34. package/dist/{child-reference-utils.js → file/child-reference.js} +1 -1
  35. package/dist/file/child-reference.js.map +1 -0
  36. package/dist/file/file-operations.d.ts.map +1 -0
  37. package/dist/{file-operations.js → file/file-operations.js} +2 -2
  38. package/dist/file/file-operations.js.map +1 -0
  39. package/dist/file/file.d.ts +263 -0
  40. package/dist/file/file.d.ts.map +1 -0
  41. package/dist/file/file.js +466 -0
  42. package/dist/file/file.js.map +1 -0
  43. package/dist/{frontmatter-utils.d.ts → file/frontmatter.d.ts} +1 -1
  44. package/dist/file/frontmatter.d.ts.map +1 -0
  45. package/dist/{frontmatter-utils.js → file/frontmatter.js} +1 -1
  46. package/dist/file/frontmatter.js.map +1 -0
  47. package/dist/file/index.d.ts +7 -0
  48. package/dist/file/index.d.ts.map +1 -0
  49. package/dist/file/index.js +7 -0
  50. package/dist/file/index.js.map +1 -0
  51. package/dist/file/link-parser.d.ts.map +1 -0
  52. package/dist/file/link-parser.js.map +1 -0
  53. package/dist/{templater-utils.d.ts → file/templater.d.ts} +1 -1
  54. package/dist/file/templater.d.ts.map +1 -0
  55. package/dist/{templater-utils.js → file/templater.js} +1 -1
  56. package/dist/file/templater.js.map +1 -0
  57. package/dist/index.d.ts +6 -15
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +12 -15
  60. package/dist/index.js.map +1 -1
  61. package/dist/settings/index.d.ts +3 -0
  62. package/dist/settings/index.d.ts.map +1 -0
  63. package/dist/settings/index.js +3 -0
  64. package/dist/settings/index.js.map +1 -0
  65. package/dist/settings/settings-store.d.ts.map +1 -0
  66. package/dist/settings/settings-store.js.map +1 -0
  67. package/dist/settings/settings-ui-builder.d.ts.map +1 -0
  68. package/dist/settings/settings-ui-builder.js.map +1 -0
  69. package/dist/string/index.d.ts +2 -0
  70. package/dist/string/index.d.ts.map +1 -0
  71. package/dist/string/index.js +2 -0
  72. package/dist/string/index.js.map +1 -0
  73. package/dist/{string-utils.d.ts → string/string.d.ts} +1 -1
  74. package/dist/string/string.d.ts.map +1 -0
  75. package/dist/{string-utils.js → string/string.js} +1 -1
  76. package/dist/string/string.js.map +1 -0
  77. package/dist/testing/mocks/obsidian.d.ts +1 -0
  78. package/dist/testing/mocks/obsidian.d.ts.map +1 -1
  79. package/dist/testing/mocks/obsidian.js +6 -0
  80. package/dist/testing/mocks/obsidian.js.map +1 -1
  81. package/package.json +3 -5
  82. package/src/async/async.ts +117 -0
  83. package/src/async/batch-operations.ts +53 -0
  84. package/src/async/index.ts +2 -0
  85. package/src/core/evaluator-base.ts +118 -0
  86. package/src/core/generate.ts +22 -0
  87. package/src/core/index.ts +2 -0
  88. package/src/date/date-recurrence.ts +244 -0
  89. package/src/date/date.ts +111 -0
  90. package/src/date/index.ts +2 -0
  91. package/src/file/child-reference.ts +76 -0
  92. package/src/file/file-operations.ts +197 -0
  93. package/src/file/file.ts +570 -0
  94. package/src/file/frontmatter.ts +80 -0
  95. package/src/file/index.ts +6 -0
  96. package/src/file/link-parser.ts +18 -0
  97. package/src/file/templater.ts +75 -0
  98. package/src/index.ts +14 -0
  99. package/src/settings/index.ts +2 -0
  100. package/src/settings/settings-store.ts +88 -0
  101. package/src/settings/settings-ui-builder.ts +507 -0
  102. package/src/string/index.ts +1 -0
  103. package/src/string/string.ts +26 -0
  104. package/src/testing/index.ts +23 -0
  105. package/src/testing/mocks/obsidian.ts +331 -0
  106. package/src/testing/mocks/utils.ts +113 -0
  107. package/src/testing/setup.ts +19 -0
  108. package/dist/async-utils.d.ts.map +0 -1
  109. package/dist/async-utils.js.map +0 -1
  110. package/dist/batch-operations.d.ts.map +0 -1
  111. package/dist/batch-operations.js.map +0 -1
  112. package/dist/child-reference-utils.d.ts.map +0 -1
  113. package/dist/child-reference-utils.js.map +0 -1
  114. package/dist/date-recurrence-utils.d.ts.map +0 -1
  115. package/dist/date-recurrence-utils.js.map +0 -1
  116. package/dist/date-utils.d.ts.map +0 -1
  117. package/dist/date-utils.js.map +0 -1
  118. package/dist/evaluator-base.d.ts.map +0 -1
  119. package/dist/evaluator-base.js.map +0 -1
  120. package/dist/file-operations.d.ts.map +0 -1
  121. package/dist/file-operations.js.map +0 -1
  122. package/dist/file-utils.d.ts +0 -6
  123. package/dist/file-utils.d.ts.map +0 -1
  124. package/dist/file-utils.js +0 -25
  125. package/dist/file-utils.js.map +0 -1
  126. package/dist/frontmatter-utils.d.ts.map +0 -1
  127. package/dist/frontmatter-utils.js.map +0 -1
  128. package/dist/generate.d.ts.map +0 -1
  129. package/dist/generate.js.map +0 -1
  130. package/dist/link-parser.d.ts.map +0 -1
  131. package/dist/link-parser.js.map +0 -1
  132. package/dist/settings-store.d.ts.map +0 -1
  133. package/dist/settings-store.js.map +0 -1
  134. package/dist/settings-ui-builder.d.ts.map +0 -1
  135. package/dist/settings-ui-builder.js.map +0 -1
  136. package/dist/string-utils.d.ts.map +0 -1
  137. package/dist/string-utils.js.map +0 -1
  138. package/dist/templater-utils.d.ts.map +0 -1
  139. package/dist/templater-utils.js.map +0 -1
  140. /package/dist/{batch-operations.d.ts → async/batch-operations.d.ts} +0 -0
  141. /package/dist/{batch-operations.js → async/batch-operations.js} +0 -0
  142. /package/dist/{evaluator-base.d.ts → core/evaluator-base.d.ts} +0 -0
  143. /package/dist/{evaluator-base.js → core/evaluator-base.js} +0 -0
  144. /package/dist/{generate.d.ts → core/generate.d.ts} +0 -0
  145. /package/dist/{generate.js → core/generate.js} +0 -0
  146. /package/dist/{file-operations.d.ts → file/file-operations.d.ts} +0 -0
  147. /package/dist/{link-parser.d.ts → file/link-parser.d.ts} +0 -0
  148. /package/dist/{link-parser.js → file/link-parser.js} +0 -0
  149. /package/dist/{settings-store.d.ts → settings/settings-store.d.ts} +0 -0
  150. /package/dist/{settings-store.js → settings/settings-store.js} +0 -0
  151. /package/dist/{settings-ui-builder.d.ts → settings/settings-ui-builder.d.ts} +0 -0
  152. /package/dist/{settings-ui-builder.js → settings/settings-ui-builder.js} +0 -0
package/README.md CHANGED
@@ -69,16 +69,36 @@ const mockFile = createMockFile('test.md');
69
69
 
70
70
  ### Available Modules
71
71
 
72
- - `async-utils` - Promise utilities and async helpers
72
+ The package is organized by domain/module:
73
+
74
+ **Settings**
75
+ - `settings-store` - Reactive settings management with Zod validation
76
+ - `settings-ui-builder` - Declarative UI builder for settings tabs
77
+
78
+ **File Operations**
79
+ - `file` - File path utilities, folder notes, and file context
80
+ - `file-operations` - File system operations and helpers
81
+ - `child-reference` - Hierarchical reference management
82
+ - `frontmatter` - Frontmatter parsing and serialization
83
+ - `link-parser` - Wiki link parsing utilities
84
+ - `templater` - Templater plugin integration
85
+
86
+ **Date Operations**
87
+ - `date` - Date/time formatting and manipulation
88
+ - `date-recurrence` - Recurrence pattern handling
89
+
90
+ **Async Utilities**
91
+ - `async` - Promise utilities and async helpers
73
92
  - `batch-operations` - Bulk processing functions
74
- - `child-reference-utils` - Hierarchical reference management
75
- - `date-recurrence-utils` - Recurrence pattern handling
76
- - `date-utils` - Date/time formatting and manipulation
77
- - `file-operations` - File system operations
78
- - `file-utils` - File path and content utilities
79
- - `settings-store` - Reactive settings management
80
- - `string-utils` - String processing functions
81
- - `templater-utils` - Template processing utilities
93
+
94
+ **String Utilities**
95
+ - `string` - String processing functions
96
+
97
+ **Core Utilities**
98
+ - `evaluator-base` - Base evaluator class
99
+ - `generate` - ID generation utilities
100
+
101
+ **Testing**
82
102
  - `testing` - Testing mocks and utilities
83
103
 
84
104
  ## TypeScript Support
@@ -66,4 +66,4 @@ export declare function onceAsyncResettable<T>(fn: () => Promise<T>): {
66
66
  execute: () => Promise<T>;
67
67
  reset: () => void;
68
68
  };
69
- //# sourceMappingURL=async-utils.d.ts.map
69
+ //# sourceMappingURL=async.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async.d.ts","sourceRoot":"","sources":["../../src/async/async.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,CAcnE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAAC,KAAK,SAAS,SAAS,OAAO,EAAE,EAAE,OAAO,EACvE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,GACtC,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAYtC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG;IAC7D,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1B,KAAK,EAAE,MAAM,IAAI,CAAC;CAClB,CAmBA"}
@@ -105,4 +105,4 @@ export function onceAsyncResettable(fn) {
105
105
  },
106
106
  };
107
107
  }
108
- //# sourceMappingURL=async-utils.js.map
108
+ //# sourceMappingURL=async.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async.js","sourceRoot":"","sources":["../../src/async/async.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,SAAS,CAAI,EAAoB;IAChD,IAAI,OAAO,GAAsB,IAAI,CAAC;IAEtC,OAAO,GAAG,EAAE;QACX,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,IAAI,CAAC;gBACJ,OAAO,GAAG,EAAE,EAAE,CAAC;YAChB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,kDAAkD;gBAClD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;QACF,CAAC;QACD,OAAO,OAAO,CAAC;IAChB,CAAC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,cAAc,CAC7B,EAAwC;IAExC,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAC;IAElD,OAAO,CAAC,GAAG,IAAW,EAAE,EAAE;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAEjC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;IACxB,CAAC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,mBAAmB,CAAI,EAAoB;IAI1D,IAAI,OAAO,GAAsB,IAAI,CAAC;IAEtC,OAAO;QACN,OAAO,EAAE,GAAG,EAAE;YACb,IAAI,CAAC,OAAO,EAAE,CAAC;gBACd,IAAI,CAAC;oBACJ,OAAO,GAAG,EAAE,EAAE,CAAC;gBAChB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,kDAAkD;oBAClD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACjC,CAAC;YACF,CAAC;YACD,OAAO,OAAO,CAAC;QAChB,CAAC;QACD,KAAK,EAAE,GAAG,EAAE;YACX,OAAO,GAAG,IAAI,CAAC;QAChB,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["/**\n * Creates a function that ensures an async operation runs only once,\n * returning the same promise for concurrent calls.\n *\n * Useful for initialization patterns where you want to ensure\n * expensive async operations (like indexing, API calls, etc.)\n * only happen once even if called multiple times.\n *\n * @param fn The async function to memoize\n * @returns A function that returns the same promise on subsequent calls\n *\n * @example\n * ```typescript\n * const initializeOnce = onceAsync(async () => {\n * await heavyInitialization();\n * console.log(\"Initialized!\");\n * });\n *\n * // All these calls will share the same promise\n * await initializeOnce();\n * await initializeOnce(); // Won't run again\n * await initializeOnce(); // Won't run again\n * ```\n */\nexport function onceAsync<T>(fn: () => Promise<T>): () => Promise<T> {\n\tlet promise: Promise<T> | null = null;\n\n\treturn () => {\n\t\tif (!promise) {\n\t\t\ttry {\n\t\t\t\tpromise = fn();\n\t\t\t} catch (error) {\n\t\t\t\t// Convert synchronous errors to rejected promises\n\t\t\t\tpromise = Promise.reject(error);\n\t\t\t}\n\t\t}\n\t\treturn promise;\n\t};\n}\n\n/**\n * Creates a function that ensures an async operation runs only once per key,\n * useful for caching expensive operations with different parameters.\n *\n * @param fn The async function to memoize\n * @returns A function that memoizes results by key\n *\n * @example\n * ```typescript\n * const fetchUserOnce = onceAsyncKeyed(async (userId: string) => {\n * return await api.getUser(userId);\n * });\n *\n * // Each unique userId will only be fetched once\n * await fetchUserOnce(\"user1\");\n * await fetchUserOnce(\"user1\"); // Returns cached promise\n * await fetchUserOnce(\"user2\"); // New fetch for different key\n * ```\n */\nexport function onceAsyncKeyed<TArgs extends readonly unknown[], TReturn>(\n\tfn: (...args: TArgs) => Promise<TReturn>\n): (...args: TArgs) => Promise<TReturn> {\n\tconst cache = new Map<string, Promise<TReturn>>();\n\n\treturn (...args: TArgs) => {\n\t\tconst key = JSON.stringify(args);\n\n\t\tif (!cache.has(key)) {\n\t\t\tcache.set(key, fn(...args));\n\t\t}\n\n\t\treturn cache.get(key)!;\n\t};\n}\n\n/**\n * Creates a resettable version of onceAsync that can be cleared and re-run.\n *\n * @param fn The async function to memoize\n * @returns Object with execute and reset methods\n *\n * @example\n * ```typescript\n * const { execute: initialize, reset } = onceAsyncResettable(async () => {\n * await heavyInitialization();\n * });\n *\n * await initialize(); // Runs\n * await initialize(); // Cached\n *\n * reset(); // Clear cache\n * await initialize(); // Runs again\n * ```\n */\nexport function onceAsyncResettable<T>(fn: () => Promise<T>): {\n\texecute: () => Promise<T>;\n\treset: () => void;\n} {\n\tlet promise: Promise<T> | null = null;\n\n\treturn {\n\t\texecute: () => {\n\t\t\tif (!promise) {\n\t\t\t\ttry {\n\t\t\t\t\tpromise = fn();\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Convert synchronous errors to rejected promises\n\t\t\t\t\tpromise = Promise.reject(error);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn promise;\n\t\t},\n\t\treset: () => {\n\t\t\tpromise = null;\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-operations.d.ts","sourceRoot":"","sources":["../../src/async/batch-operations.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,iBAAiB,CAAC,CAAC,EACxC,KAAK,EAAE,CAAC,EAAE,EACV,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,EACnC,UAAU,GAAE,OAAc,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAmB/B;AAED,wBAAgB,wBAAwB,CACvC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAChB,IAAI,CAUN"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-operations.js","sourceRoot":"","sources":["../../src/async/batch-operations.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAYlC,MAAM,UAAgB,iBAAiB;yDACtC,KAAU,EACV,cAAsB,EACtB,OAAmC,EACnC,aAAsB,IAAI;QAE1B,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACJ,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;gBACpB,YAAY,EAAE,CAAC;YAChB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,OAAO,CAAC,KAAK,CAAC,GAAG,cAAc,0BAA0B,EAAE,KAAK,CAAC,CAAC;gBAClE,UAAU,EAAE,CAAC;YACd,CAAC;QACF,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YAChB,wBAAwB,CAAC,cAAc,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;QACpE,CAAC;QAED,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;IACrC,CAAC;CAAA;AAED,MAAM,UAAU,wBAAwB,CACvC,SAAiB,EACjB,YAAoB,EACpB,UAAkB;IAElB,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;QACtB,IAAI,MAAM,CACT,GAAG,SAAS,KAAK,YAAY,QAAQ,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,yBAAyB,CAC3F,CAAC;IACH,CAAC;SAAM,CAAC;QACP,IAAI,MAAM,CACT,GAAG,SAAS,KAAK,YAAY,eAAe,UAAU,qCAAqC,CAC3F,CAAC;IACH,CAAC;AACF,CAAC","sourcesContent":["import { Notice } from \"obsidian\";\n\nexport interface BatchOperationOptions {\n\tcloseAfter?: boolean;\n\tcallOnComplete?: boolean;\n}\n\nexport interface BatchOperationResult {\n\tsuccessCount: number;\n\terrorCount: number;\n}\n\nexport async function runBatchOperation<T>(\n\titems: T[],\n\toperationLabel: string,\n\thandler: (item: T) => Promise<void>,\n\tshowResult: boolean = true\n): Promise<BatchOperationResult> {\n\tlet successCount = 0;\n\tlet errorCount = 0;\n\n\tfor (const item of items) {\n\t\ttry {\n\t\t\tawait handler(item);\n\t\t\tsuccessCount++;\n\t\t} catch (error) {\n\t\t\tconsole.error(`${operationLabel}: error processing item:`, error);\n\t\t\terrorCount++;\n\t\t}\n\t}\n\n\tif (showResult) {\n\t\tshowBatchOperationResult(operationLabel, successCount, errorCount);\n\t}\n\n\treturn { successCount, errorCount };\n}\n\nexport function showBatchOperationResult(\n\toperation: string,\n\tsuccessCount: number,\n\terrorCount: number\n): void {\n\tif (errorCount === 0) {\n\t\tnew Notice(\n\t\t\t`${operation}: ${successCount} item${successCount === 1 ? \"\" : \"s\"} processed successfully`\n\t\t);\n\t} else {\n\t\tnew Notice(\n\t\t\t`${operation}: ${successCount} succeeded, ${errorCount} failed. Check console for details.`\n\t\t);\n\t}\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export * from "./async";
2
+ export * from "./batch-operations";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/async/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from "./async";
2
+ export * from "./batch-operations";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/async/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC","sourcesContent":["export * from \"./async\";\nexport * from \"./batch-operations\";\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator-base.d.ts","sourceRoot":"","sources":["../../src/core/evaluator-base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,MAAM,CAAC;AAE1D,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,8BAAsB,aAAa,CAAC,KAAK,SAAS,QAAQ,EAAE,SAAS;IACpE,SAAS,CAAC,aAAa,EAAE,KAAK,CAC7B,KAAK,GAAG;QAAE,EAAE,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAA;KAAE,CACjE,CAAM;IACP,OAAO,CAAC,oBAAoB,CAA6B;gBAE7C,aAAa,EAAE,eAAe,CAAC,SAAS,CAAC;IAUrD;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,QAAQ,EAAE,SAAS,GAAG,KAAK,EAAE;IAE7D;;OAEG;IACH,OAAO,CAAC,YAAY;IA6BpB;;OAEG;IACH,SAAS,CAAC,YAAY,CACrB,IAAI,EAAE,KAAK,GAAG;QAAE,EAAE,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAA;KAAE,EACvE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,GAAG,SAAS;IAStB;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO;IAIxD;;OAEG;IACH,OAAO,IAAI,IAAI;IAQf;;OAEG;IACH,kBAAkB,IAAI,MAAM;IAI5B;;OAEG;IACH,WAAW,IAAI,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CAShF"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator-base.js","sourceRoot":"","sources":["../../src/core/evaluator-base.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BehaviorSubject, Subscription } from \"rxjs\";\n\nexport interface BaseRule {\n\tid: string;\n\texpression: string;\n\tenabled: boolean;\n}\n\n/**\n * Generic base class for evaluating JavaScript expressions against frontmatter objects.\n * Provides reactive compilation of rules via RxJS subscription and safe evaluation.\n */\nexport abstract class BaseEvaluator<TRule extends BaseRule, TSettings> {\n\tprotected compiledRules: Array<\n\t\tTRule & { fn: (frontmatter: Record<string, unknown>) => boolean }\n\t> = [];\n\tprivate settingsSubscription: Subscription | null = null;\n\n\tconstructor(settingsStore: BehaviorSubject<TSettings>) {\n\t\tconst initialRules = this.extractRules(settingsStore.value);\n\t\tthis.compileRules(initialRules);\n\n\t\tthis.settingsSubscription = settingsStore.subscribe((settings) => {\n\t\t\tconst newRules = this.extractRules(settings);\n\t\t\tthis.compileRules(newRules);\n\t\t});\n\t}\n\n\t/**\n\t * Extract rules from settings object. Must be implemented by subclasses.\n\t */\n\tprotected abstract extractRules(settings: TSettings): TRule[];\n\n\t/**\n\t * Compile rules into executable functions with error handling.\n\t */\n\tprivate compileRules(rules: TRule[]): void {\n\t\tthis.compiledRules = [];\n\n\t\tfor (const rule of rules) {\n\t\t\tif (!rule.enabled || !rule.expression.trim()) continue;\n\n\t\t\ttry {\n\t\t\t\tconst cleanExpression = rule.expression.trim();\n\n\t\t\t\t// Create a function that takes 'fm' (frontmatter) as parameter\n\t\t\t\t// and evaluates the expression in that context\n\t\t\t\tconst fn = new Function(\"fm\", `return (${cleanExpression});`) as (\n\t\t\t\t\tfrontmatter: Record<string, unknown>\n\t\t\t\t) => boolean;\n\n\t\t\t\t// Test the function with a dummy object to catch syntax errors early\n\t\t\t\tfn({});\n\n\t\t\t\tthis.compiledRules.push({\n\t\t\t\t\t...rule,\n\t\t\t\t\texpression: cleanExpression,\n\t\t\t\t\tfn,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.warn(`Invalid rule expression \"${rule.expression}\":`, error);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Evaluate a single rule against frontmatter. Returns the result or undefined if error.\n\t */\n\tprotected evaluateRule(\n\t\trule: TRule & { fn: (frontmatter: Record<string, unknown>) => boolean },\n\t\tfrontmatter: Record<string, unknown>\n\t): boolean | undefined {\n\t\ttry {\n\t\t\treturn rule.fn(frontmatter);\n\t\t} catch (error) {\n\t\t\tconsole.warn(`Error evaluating rule \"${rule.expression}\":`, error);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t/**\n\t * Convert evaluation result to boolean - only explicit true is considered truthy.\n\t */\n\tprotected isTruthy(result: boolean | undefined): boolean {\n\t\treturn result === true;\n\t}\n\n\t/**\n\t * Clean up subscriptions and compiled rules.\n\t */\n\tdestroy(): void {\n\t\tif (this.settingsSubscription) {\n\t\t\tthis.settingsSubscription.unsubscribe();\n\t\t\tthis.settingsSubscription = null;\n\t\t}\n\t\tthis.compiledRules = [];\n\t}\n\n\t/**\n\t * Get the number of active (compiled) rules.\n\t */\n\tgetActiveRuleCount(): number {\n\t\treturn this.compiledRules.length;\n\t}\n\n\t/**\n\t * Get information about all rules including their validity.\n\t */\n\tgetRuleInfo(): Array<{ expression: string; isValid: boolean; enabled: boolean }> {\n\t\tconst validExpressions = new Set(this.compiledRules.map((r) => r.expression));\n\n\t\treturn this.compiledRules.map((rule) => ({\n\t\t\texpression: rule.expression,\n\t\t\tisValid: validExpressions.has(rule.expression),\n\t\t\tenabled: rule.enabled,\n\t\t}));\n\t}\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/core/generate.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,gBAAgB,QAAO,MAMnC,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,aAQrC,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/core/generate.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAW,EAAE;IAC5C,MAAM,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC;IACpC,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACxE,OAAO,MAAM,CACZ,GAAG,gBAAgB,CAAC,WAAW,EAAE,GAAG,WAAW,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,GAAG,WAAW,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,GAAG,WAAW,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,GAAG,WAAW,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,EAAE,CACjQ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAkB,EAAE;IACrD,MAAM,WAAW,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAChF,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC;IAE/B,MAAM,kBAAkB,GAAW,GAAG,WAAW,CAAC,WAAW,EAAE,IAAI,WAAW,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,WAAW,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;IACnJ,MAAM,cAAc,GAAW,gBAAgB,EAAE,CAAC;IAElD,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;AACpE,CAAC,CAAC","sourcesContent":["export interface TimestampData {\n\tstartDate: string;\n\tzettelId: number;\n}\n\nexport const generateZettelId = (): number => {\n\tconst currentTimestamp = new Date();\n\tconst padWithZero = (number: number) => String(number).padStart(2, \"0\");\n\treturn Number(\n\t\t`${currentTimestamp.getFullYear()}${padWithZero(currentTimestamp.getMonth() + 1)}${padWithZero(currentTimestamp.getDate())}${padWithZero(currentTimestamp.getHours())}${padWithZero(currentTimestamp.getMinutes())}${padWithZero(currentTimestamp.getSeconds())}`\n\t);\n};\n\nexport const generateTimestamps = (): TimestampData => {\n\tconst padWithZero = (number: number): string => String(number).padStart(2, \"0\");\n\tconst currentDate = new Date();\n\n\tconst formattedStartDate: string = `${currentDate.getFullYear()}-${padWithZero(currentDate.getMonth() + 1)}-${padWithZero(currentDate.getDate())}`;\n\tconst uniqueZettelId: number = generateZettelId();\n\n\treturn { startDate: formattedStartDate, zettelId: uniqueZettelId };\n};\n"]}
@@ -0,0 +1,3 @@
1
+ export * from "./evaluator-base";
2
+ export * from "./generate";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from "./evaluator-base";
2
+ export * from "./generate";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC","sourcesContent":["export * from \"./evaluator-base\";\nexport * from \"./generate\";\n"]}
@@ -27,4 +27,4 @@ export declare function iterateOccurrencesInRange(startDate: DateTime, rrules: {
27
27
  */
28
28
  export declare function calculateInstanceDateTime(instanceDate: DateTime, timeString?: string): DateTime;
29
29
  export declare function calculateRecurringInstanceDateTime(nextInstanceDateTime: DateTime, nodeRecuringEventDateTime: DateTime, recurrenceType: RecurrenceType, allDay?: boolean): DateTime;
30
- //# sourceMappingURL=date-recurrence-utils.d.ts.map
30
+ //# sourceMappingURL=date-recurrence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-recurrence.d.ts","sourceRoot":"","sources":["../../src/date/date-recurrence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEtC,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEpG,MAAM,MAAM,OAAO,GAChB,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,WAAW,GACX,UAAU,GACV,QAAQ,GACR,UAAU,CAAC;AAEd,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAQrD,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAChC,WAAW,EAAE,QAAQ,EACrB,cAAc,EAAE,cAAc,EAC9B,QAAQ,CAAC,EAAE,OAAO,EAAE,GAClB,QAAQ,CAuBV;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAQ7E;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,QAAQ,CAgB7F;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,QAAQ,CAI9F;AAED,wBAAiB,yBAAyB,CACzC,SAAS,EAAE,QAAQ,EACnB,MAAM,EAAE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,EACtD,UAAU,EAAE,QAAQ,EACpB,QAAQ,EAAE,QAAQ,GAChB,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CA+DpC;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,CAO/F;AAED,wBAAgB,kCAAkC,CACjD,oBAAoB,EAAE,QAAQ,EAC9B,yBAAyB,EAAE,QAAQ,EACnC,cAAc,EAAE,cAAc,EAC9B,MAAM,CAAC,EAAE,OAAO,GACd,QAAQ,CA0DV"}
@@ -185,4 +185,4 @@ export function calculateRecurringInstanceDateTime(nextInstanceDateTime, nodeRec
185
185
  return nextInstanceDateTime.startOf("day");
186
186
  }
187
187
  }
188
- //# sourceMappingURL=date-recurrence-utils.js.map
188
+ //# sourceMappingURL=date-recurrence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-recurrence.js","sourceRoot":"","sources":["../../src/date/date-recurrence.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DateTime } from \"luxon\";\n\nexport type RecurrenceType = \"daily\" | \"weekly\" | \"bi-weekly\" | \"monthly\" | \"bi-monthly\" | \"yearly\";\n\nexport type Weekday =\n\t| \"sunday\"\n\t| \"monday\"\n\t| \"tuesday\"\n\t| \"wednesday\"\n\t| \"thursday\"\n\t| \"friday\"\n\t| \"saturday\";\n\nexport const WEEKDAY_TO_NUMBER: Record<Weekday, number> = {\n\tsunday: 0,\n\tmonday: 1,\n\ttuesday: 2,\n\twednesday: 3,\n\tthursday: 4,\n\tfriday: 5,\n\tsaturday: 6,\n};\n\n/**\n * Calculates the next occurrence date based on recurrence type and optional weekdays\n */\nexport function getNextOccurrence(\n\tcurrentDate: DateTime,\n\trecurrenceType: RecurrenceType,\n\tweekdays?: Weekday[]\n): DateTime {\n\tswitch (recurrenceType) {\n\t\tcase \"daily\":\n\t\t\treturn currentDate.plus({ days: 1 });\n\t\tcase \"weekly\":\n\t\t\tif (weekdays && weekdays.length > 0) {\n\t\t\t\treturn getNextWeekdayOccurrence(currentDate, weekdays);\n\t\t\t}\n\t\t\treturn currentDate.plus({ weeks: 1 });\n\t\tcase \"bi-weekly\":\n\t\t\tif (weekdays && weekdays.length > 0) {\n\t\t\t\treturn getNextBiWeeklyOccurrence(currentDate, weekdays);\n\t\t\t}\n\t\t\treturn currentDate.plus({ weeks: 2 });\n\t\tcase \"monthly\":\n\t\t\treturn currentDate.plus({ months: 1 });\n\t\tcase \"bi-monthly\":\n\t\t\treturn currentDate.plus({ months: 2 });\n\t\tcase \"yearly\":\n\t\t\treturn currentDate.plus({ years: 1 });\n\t\tdefault:\n\t\t\treturn currentDate.plus({ days: 1 });\n\t}\n}\n\n/**\n * Checks if a given date matches any of the specified weekdays\n */\nexport function isDateOnWeekdays(date: DateTime, weekdays: Weekday[]): boolean {\n\tconst dateWeekday = date.weekday;\n\tconst luxonWeekdays = weekdays.map((day) => {\n\t\tconst dayNumber = WEEKDAY_TO_NUMBER[day];\n\t\treturn dayNumber === 0 ? 7 : dayNumber; // Convert Sunday from 0 to 7 for Luxon\n\t});\n\n\treturn luxonWeekdays.includes(dateWeekday);\n}\n\n/**\n * Finds the next occurrence on specified weekdays\n */\nexport function getNextWeekdayOccurrence(currentDate: DateTime, weekdays: Weekday[]): DateTime {\n\tconst currentWeekday = currentDate.weekday;\n\tconst luxonWeekdays = weekdays.map((day) => {\n\t\tconst dayNumber = WEEKDAY_TO_NUMBER[day];\n\t\treturn dayNumber === 0 ? 7 : dayNumber; // Convert Sunday from 0 to 7 for Luxon\n\t});\n\n\t// Find next weekday in the current week (after today)\n\tconst nextWeekday = luxonWeekdays.find((day) => day > currentWeekday);\n\tif (nextWeekday) {\n\t\treturn currentDate.set({ weekday: nextWeekday as 1 | 2 | 3 | 4 | 5 | 6 | 7 });\n\t}\n\n\t// No more weekdays this week, go to first weekday of next week\n\tconst firstWeekday = Math.min(...luxonWeekdays);\n\treturn currentDate.plus({ weeks: 1 }).set({ weekday: firstWeekday as 1 | 2 | 3 | 4 | 5 | 6 | 7 });\n}\n\n/**\n * Finds the next bi-weekly occurrence on specified weekdays\n */\nexport function getNextBiWeeklyOccurrence(currentDate: DateTime, weekdays: Weekday[]): DateTime {\n\tconst nextWeekly = getNextWeekdayOccurrence(currentDate, weekdays);\n\t// Add one more week to make it bi-weekly\n\treturn nextWeekly.plus({ weeks: 1 });\n}\n\nexport function* iterateOccurrencesInRange(\n\tstartDate: DateTime,\n\trrules: { type: RecurrenceType; weekdays?: Weekday[] },\n\trangeStart: DateTime,\n\trangeEnd: DateTime\n): Generator<DateTime, void, unknown> {\n\t// Normalize to start of day for comparison\n\tconst normalizedStart = startDate.startOf(\"day\");\n\tconst normalizedRangeStart = rangeStart.startOf(\"day\");\n\tconst normalizedRangeEnd = rangeEnd.startOf(\"day\");\n\n\t// Start from the later of startDate or rangeStart\n\tlet currentDate =\n\t\tnormalizedStart >= normalizedRangeStart ? normalizedStart : normalizedRangeStart;\n\n\t// For weekly/bi-weekly with weekdays, we need to track which week we're in\n\tif (\n\t\t(rrules.type === \"weekly\" || rrules.type === \"bi-weekly\") &&\n\t\trrules.weekdays &&\n\t\trrules.weekdays.length > 0\n\t) {\n\t\t// Calculate week offset from start date\n\t\tconst weeksFromStart = Math.floor(currentDate.diff(normalizedStart, \"weeks\").weeks);\n\n\t\t// For bi-weekly, we only want even weeks (0, 2, 4...) from the start date\n\t\tconst weekInterval = rrules.type === \"bi-weekly\" ? 2 : 1;\n\n\t\t// Adjust to the correct week if we're in an off-week\n\t\tconst weekOffset = weeksFromStart % weekInterval;\n\t\tif (weekOffset !== 0) {\n\t\t\tcurrentDate = currentDate.plus({ weeks: weekInterval - weekOffset });\n\t\t}\n\n\t\t// Now iterate through weeks, checking each day\n\t\twhile (currentDate <= normalizedRangeEnd) {\n\t\t\t// Check all 7 days of the current week\n\t\t\tfor (let dayOffset = 0; dayOffset < 7; dayOffset++) {\n\t\t\t\tconst checkDate = currentDate.plus({ days: dayOffset });\n\n\t\t\t\t// Only yield if within range and matches a target weekday\n\t\t\t\tif (\n\t\t\t\t\tcheckDate >= normalizedRangeStart &&\n\t\t\t\t\tcheckDate <= normalizedRangeEnd &&\n\t\t\t\t\tisDateOnWeekdays(checkDate, rrules.weekdays)\n\t\t\t\t) {\n\t\t\t\t\tyield checkDate;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Move to next occurrence week (1 week for weekly, 2 weeks for bi-weekly)\n\t\t\tcurrentDate = currentDate.plus({ weeks: weekInterval });\n\t\t}\n\t} else {\n\t\t// For other recurrence types (daily, monthly, yearly, or weekly without weekdays)\n\t\twhile (currentDate <= normalizedRangeEnd) {\n\t\t\tif (currentDate >= normalizedRangeStart) {\n\t\t\t\tyield currentDate;\n\t\t\t}\n\n\t\t\tconst nextDate = getNextOccurrence(currentDate, rrules.type, rrules.weekdays);\n\n\t\t\tif (nextDate <= normalizedRangeEnd) {\n\t\t\t\tcurrentDate = nextDate;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Calculates a DateTime for a specific date with optional time\n */\nexport function calculateInstanceDateTime(instanceDate: DateTime, timeString?: string): DateTime {\n\tif (!timeString) {\n\t\treturn instanceDate.startOf(\"day\");\n\t}\n\n\tconst [hours, minutes] = timeString.split(\":\").map(Number);\n\treturn instanceDate.set({ hour: hours, minute: minutes, second: 0, millisecond: 0 });\n}\n\nexport function calculateRecurringInstanceDateTime(\n\tnextInstanceDateTime: DateTime,\n\tnodeRecuringEventDateTime: DateTime,\n\trecurrenceType: RecurrenceType,\n\tallDay?: boolean\n): DateTime {\n\t// Convert the original event time to the target timezone once to preserve local time\n\tconst originalInTargetZone = nodeRecuringEventDateTime.setZone(nextInstanceDateTime.zone);\n\n\tswitch (recurrenceType) {\n\t\tcase \"daily\":\n\t\tcase \"weekly\":\n\t\tcase \"bi-weekly\": {\n\t\t\tif (allDay) {\n\t\t\t\treturn nextInstanceDateTime.startOf(\"day\");\n\t\t\t}\n\n\t\t\treturn nextInstanceDateTime.set({\n\t\t\t\thour: originalInTargetZone.hour,\n\t\t\t\tminute: originalInTargetZone.minute,\n\t\t\t\tsecond: 0,\n\t\t\t\tmillisecond: 0,\n\t\t\t});\n\t\t}\n\n\t\tcase \"monthly\":\n\t\tcase \"bi-monthly\": {\n\t\t\tif (allDay) {\n\t\t\t\treturn nextInstanceDateTime.set({ day: originalInTargetZone.day }).startOf(\"day\");\n\t\t\t}\n\n\t\t\treturn nextInstanceDateTime.set({\n\t\t\t\tday: originalInTargetZone.day,\n\t\t\t\thour: originalInTargetZone.hour,\n\t\t\t\tminute: originalInTargetZone.minute,\n\t\t\t\tsecond: 0,\n\t\t\t\tmillisecond: 0,\n\t\t\t});\n\t\t}\n\n\t\tcase \"yearly\": {\n\t\t\tif (allDay) {\n\t\t\t\treturn nextInstanceDateTime\n\t\t\t\t\t.set({\n\t\t\t\t\t\tmonth: originalInTargetZone.month,\n\t\t\t\t\t\tday: originalInTargetZone.day,\n\t\t\t\t\t})\n\t\t\t\t\t.startOf(\"day\");\n\t\t\t}\n\n\t\t\treturn nextInstanceDateTime.set({\n\t\t\t\tmonth: originalInTargetZone.month,\n\t\t\t\tday: originalInTargetZone.day,\n\t\t\t\thour: originalInTargetZone.hour,\n\t\t\t\tminute: originalInTargetZone.minute,\n\t\t\t\tsecond: 0,\n\t\t\t\tmillisecond: 0,\n\t\t\t});\n\t\t}\n\n\t\tdefault:\n\t\t\treturn nextInstanceDateTime.startOf(\"day\");\n\t}\n}\n"]}
@@ -18,4 +18,4 @@ export declare const parseTimeString: (value: string | null) => DateTime | undef
18
18
  * Supports multiple formats including date-only and datetime formats
19
19
  */
20
20
  export declare const parseDateTimeString: (value: string | null) => DateTime | undefined;
21
- //# sourceMappingURL=date-utils.d.ts.map
21
+ //# sourceMappingURL=date.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/date/date.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,eAAO,MAAM,sBAAsB,GAAI,YAAY,MAAM,KAAG,MAgB3D,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,YAAY,MAAM,KAAG,MAavD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,YAAY,MAAM,KAAG,MAAM,GAAG,IAMnE,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,MAIhD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,GAAG,IAAI,KAAG,QAAQ,GAAG,SAgBjE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,GAAG,IAAI,KAAG,QAAQ,GAAG,SA8BrE,CAAC"}
@@ -102,4 +102,4 @@ export const parseDateTimeString = (value) => {
102
102
  return dt;
103
103
  return undefined;
104
104
  };
105
- //# sourceMappingURL=date-utils.js.map
105
+ //# sourceMappingURL=date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.js","sourceRoot":"","sources":["../../src/date/date.ts"],"names":[],"mappings":"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","sourcesContent":["import { DateTime } from \"luxon\";\n\nexport const formatDateTimeForInput = (dateString: string): string => {\n\tif (!dateString) return \"\";\n\n\ttry {\n\t\tconst date = new Date(dateString);\n\t\t// Format for datetime-local input (YYYY-MM-DDTHH:mm)\n\t\tconst year = date.getFullYear();\n\t\tconst month = String(date.getMonth() + 1).padStart(2, \"0\");\n\t\tconst day = String(date.getDate()).padStart(2, \"0\");\n\t\tconst hours = String(date.getHours()).padStart(2, \"0\");\n\t\tconst minutes = String(date.getMinutes()).padStart(2, \"0\");\n\n\t\treturn `${year}-${month}-${day}T${hours}:${minutes}`;\n\t} catch {\n\t\treturn \"\";\n\t}\n};\n\nexport const formatDateForInput = (dateString: string): string => {\n\tif (!dateString) return \"\";\n\n\ttry {\n\t\tconst date = new Date(dateString);\n\t\tconst year = date.getFullYear();\n\t\tconst month = String(date.getMonth() + 1).padStart(2, \"0\");\n\t\tconst day = String(date.getDate()).padStart(2, \"0\");\n\n\t\treturn `${year}-${month}-${day}`;\n\t} catch {\n\t\treturn \"\";\n\t}\n};\n\n/**\n * Converts input value to ISO string, handling edge cases where\n * browser datetime-local inputs behave differently across platforms.\n * Returns null for invalid dates to prevent silent failures.\n */\nexport const inputValueToISOString = (inputValue: string): string | null => {\n\ttry {\n\t\treturn new Date(inputValue).toISOString();\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nexport const formatDuration = (minutes: number): string => {\n\tconst hours = Math.floor(minutes / 60);\n\tconst mins = minutes % 60;\n\treturn `${String(hours).padStart(2, \"0\")}:${String(mins).padStart(2, \"0\")}:00`;\n};\n\n/**\n * Parse time string from datetime value - returns DateTime object\n * Rejects plain HH:mm format, requires full datetime\n */\nexport const parseTimeString = (value: string | null): DateTime | undefined => {\n\tif (value === null) return undefined;\n\n\tconst v = value.trim();\n\n\t// Reject plain HH:mm format - require full datetime\n\tif (/^\\d{2}:\\d{2}$/.test(v)) {\n\t\treturn undefined; // Reject plain time format\n\t}\n\n\t// Try ISO format first (most common) - EXACT same logic as recurring events\n\tlet dt = DateTime.fromISO(v, { setZone: true }); // ISO: with/without seconds, Z/offset, T\n\tif (!dt.isValid) dt = DateTime.fromSQL(v, { setZone: true }); // \"YYYY-MM-DD HH:mm[:ss]\" etc.\n\tif (!dt.isValid) dt = DateTime.fromFormat(v, \"yyyy-MM-dd HH:mm\", { setZone: true });\n\n\treturn dt.isValid ? dt : undefined;\n};\n\n/**\n * Parse and validate datetime strings for event parsing\n * Supports multiple formats including date-only and datetime formats\n */\nexport const parseDateTimeString = (value: string | null): DateTime | undefined => {\n\tif (value === null) return undefined;\n\n\tconst v = value.trim();\n\tif (!v) return undefined;\n\n\t// Try multiple datetime formats in order of preference\n\tlet dt: DateTime;\n\n\t// 1. Try ISO format first (most common)\n\tdt = DateTime.fromISO(v, { setZone: true });\n\tif (dt.isValid) return dt;\n\n\t// 2. Try SQL format (YYYY-MM-DD HH:mm:ss)\n\tdt = DateTime.fromSQL(v, { setZone: true });\n\tif (dt.isValid) return dt;\n\n\t// 3. Try common format with space (YYYY-MM-DD HH:mm)\n\tdt = DateTime.fromFormat(v, \"yyyy-MM-dd HH:mm\", { setZone: true });\n\tif (dt.isValid) return dt;\n\n\t// 4. Try date-only format (YYYY-MM-DD) - treat as start of day\n\tdt = DateTime.fromFormat(v, \"yyyy-MM-dd\", { setZone: true });\n\tif (dt.isValid) return dt;\n\n\t// 5. Try ISO date format (YYYY-MM-DD)\n\tdt = DateTime.fromISO(v, { setZone: true });\n\tif (dt.isValid) return dt;\n\n\treturn undefined;\n};\n"]}
@@ -0,0 +1,3 @@
1
+ export * from "./date";
2
+ export * from "./date-recurrence";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/date/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from "./date";
2
+ export * from "./date-recurrence";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/date/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC","sourcesContent":["export * from \"./date\";\nexport * from \"./date-recurrence\";\n"]}
@@ -6,4 +6,4 @@ export declare function extractDirectoryPath(filePath: string): string;
6
6
  export declare function isRelativeChildReference(childRef: string): boolean;
7
7
  export declare function normalizeChildReference(childRef: string, vault: VaultAdapter, currentFileDirectory?: string): string;
8
8
  export declare function normalizeChildReferences(childRefs: string[], vault: VaultAdapter, currentFileDirectory?: string): string[];
9
- //# sourceMappingURL=child-reference-utils.d.ts.map
9
+ //# sourceMappingURL=child-reference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-reference.d.ts","sourceRoot":"","sources":["../../src/file/child-reference.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAIjC,MAAM,WAAW,YAAY;IAC5B,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;CAClD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM7D;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAMlE;AAED,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,oBAAoB,CAAC,EAAE,MAAM,GAC3B,MAAM,CAqCR;AAED,wBAAgB,wBAAwB,CACvC,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,EAAE,YAAY,EACnB,oBAAoB,CAAC,EAAE,MAAM,GAC3B,MAAM,EAAE,CAIV"}
@@ -54,4 +54,4 @@ export function normalizeChildReferences(childRefs, vault, currentFileDirectory)
54
54
  return normalizeChildReference(childRef, vault, currentFileDirectory);
55
55
  });
56
56
  }
57
- //# sourceMappingURL=child-reference-utils.js.map
57
+ //# sourceMappingURL=child-reference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-reference.js","sourceRoot":"","sources":["../../src/file/child-reference.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAMxD,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACpD,MAAM,cAAc,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjD,IAAI,cAAc,KAAK,CAAC,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,QAAgB;IACxD,MAAM,QAAQ,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,uBAAuB,CACtC,QAAgB,EAChB,KAAmB,EACnB,oBAA6B;IAE7B,MAAM,QAAQ,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAEnD,qDAAqD;IACrD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,uEAAuE;QACvE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,oBAAoB,KAAK,SAAS,EAAE,CAAC;YACnE,2EAA2E;YAC3E,MAAM,aAAa,GAAG,oBAAoB;gBACzC,CAAC,CAAC,GAAG,oBAAoB,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,KAAK,EAAE;gBACrF,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;oBACzB,CAAC,CAAC,QAAQ;oBACV,CAAC,CAAC,GAAG,QAAQ,KAAK,CAAC;YACrB,MAAM,IAAI,GAAG,KAAK,CAAC,qBAAqB,CAAC,aAAa,CAAC,CAAC;YACxD,IAAI,IAAI,YAAY,KAAK,EAAE,CAAC;gBAC3B,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC;QACF,CAAC;QACD,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,qDAAqD;IACrD,IAAI,wBAAwB,CAAC,QAAQ,CAAC,IAAI,oBAAoB,EAAE,CAAC;QAChE,MAAM,YAAY,GAAG,GAAG,oBAAoB,IAAI,QAAQ,EAAE,CAAC;QAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC;QACvD,IAAI,IAAI,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;IACF,CAAC;IAED,mFAAmF;IACnF,MAAM,IAAI,GAAG,KAAK,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACnD,IAAI,IAAI,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,wBAAwB,CACvC,SAAmB,EACnB,KAAmB,EACnB,oBAA6B;IAE7B,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QACjC,OAAO,uBAAuB,CAAC,QAAQ,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { TFile } from \"obsidian\";\nimport { createFileLink } from \"./file-operations\";\nimport { extractFilePathFromLink } from \"./link-parser\";\n\nexport interface VaultAdapter {\n\tgetAbstractFileByPath(path: string): TFile | null;\n}\n\nexport function extractDirectoryPath(filePath: string): string {\n\tconst lastSlashIndex = filePath.lastIndexOf(\"/\");\n\tif (lastSlashIndex === -1) {\n\t\treturn \"\";\n\t}\n\treturn filePath.substring(0, lastSlashIndex);\n}\n\nexport function isRelativeChildReference(childRef: string): boolean {\n\tconst filePath = extractFilePathFromLink(childRef);\n\tif (!filePath) {\n\t\treturn !childRef.includes(\"/\");\n\t}\n\treturn !filePath.includes(\"/\");\n}\n\nexport function normalizeChildReference(\n\tchildRef: string,\n\tvault: VaultAdapter,\n\tcurrentFileDirectory?: string\n): string {\n\tconst filePath = extractFilePathFromLink(childRef);\n\n\t// Handle plain text references (not wrapped in [[]])\n\tif (!filePath) {\n\t\t// If it's not a link format, check if it should be converted to a link\n\t\tif (!childRef.includes(\"/\") && currentFileDirectory !== undefined) {\n\t\t\t// This is a plain text reference that might need to be converted to a link\n\t\t\tconst potentialPath = currentFileDirectory\n\t\t\t\t? `${currentFileDirectory}/${childRef.endsWith(\".md\") ? childRef : `${childRef}.md`}`\n\t\t\t\t: childRef.endsWith(\".md\")\n\t\t\t\t\t? childRef\n\t\t\t\t\t: `${childRef}.md`;\n\t\t\tconst file = vault.getAbstractFileByPath(potentialPath);\n\t\t\tif (file instanceof TFile) {\n\t\t\t\treturn createFileLink(file);\n\t\t\t}\n\t\t}\n\t\treturn childRef;\n\t}\n\n\t// Handle relative references by making them absolute\n\tif (isRelativeChildReference(childRef) && currentFileDirectory) {\n\t\tconst absolutePath = `${currentFileDirectory}/${filePath}`;\n\t\tconst file = vault.getAbstractFileByPath(absolutePath);\n\t\tif (file instanceof TFile) {\n\t\t\treturn createFileLink(file);\n\t\t}\n\t}\n\n\t// For absolute references or when no directory context, try to find the file as-is\n\tconst file = vault.getAbstractFileByPath(filePath);\n\tif (file instanceof TFile) {\n\t\treturn createFileLink(file);\n\t}\n\n\treturn childRef;\n}\n\nexport function normalizeChildReferences(\n\tchildRefs: string[],\n\tvault: VaultAdapter,\n\tcurrentFileDirectory?: string\n): string[] {\n\treturn childRefs.map((childRef) => {\n\t\treturn normalizeChildReference(childRef, vault, currentFileDirectory);\n\t});\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-operations.d.ts","sourceRoot":"","sources":["../../src/file/file-operations.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,GAAG,EAAU,KAAK,EAAE,MAAM,UAAU,CAAC;AAKnD,eAAO,MAAM,QAAQ,GAAI,cAAc,MAAM,KAAG,MAE/C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,KAAK,GAAG,KAAG,KAO/C,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAU,KAAK,GAAG,EAAE,cAAc,MAAM,KAAG,OAAO,CAAC,MAAM,CAQvF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAU,KAAK,GAAG,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,IAAI,CAInF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,KAAK,GAAG,EAAE,MAAM,KAAK,KAAG,OAAO,CAAC,IAAI,CAE3E,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAU,eAAe,MAAM,KAAG,OAAO,CAAC,MAAM,EAAE,CAejF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,KAAK,GAAG,EAAE,kBAAkB,MAAM,KAAG,KAAK,GAAG,IAclF,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,KAAK,KAAG,MAG5C,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,KAAG,MAAM,EAW3E,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,GAAG,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,KAAG,OAEtD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,KAAG,MAelD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAU,CAAC,EACxC,KAAK,GAAG,EACR,OAAO,GAAG,EACV,WAAW,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,eAAc,MAA2B,KACvC,OAAO,CAAC,CAAC,GAAG,IAAI,CAgBlB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,QAAQ,GAAU,CAAC,EAC/B,KAAK,GAAG,EACR,UAAU,MAAM,EAChB,WAAW,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,eAAc,MAA2B,KACvC,OAAO,CAAC,CAAC,GAAG,IAAI,CAelB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,4BAA4B,GACxC,KAAK,GAAG,EACR,MAAM,KAAK,EACX,eAAe,MAAM,KACnB,OAAO,CAAC,KAAK,CAoBf,CAAC"}
@@ -2,6 +2,8 @@ import { __awaiter } from "tslib";
2
2
  import * as fs from "node:fs/promises";
3
3
  import * as path from "node:path";
4
4
  import { Notice, TFile } from "obsidian";
5
+ import { generateZettelId } from "../core";
6
+ import { generateUniqueFilePath } from "./file";
5
7
  import { extractFilePathFromLink } from "./link-parser";
6
8
  export const fromRoot = (relativePath) => {
7
9
  return path.resolve(__dirname, `../../../${relativePath}`);
@@ -140,8 +142,6 @@ export const withFile = (app_1, filePath_1, operation_1, ...args_1) => __awaiter
140
142
  export const duplicateFileWithNewZettelId = (app, file, zettelIdProp) => __awaiter(void 0, void 0, void 0, function* () {
141
143
  var _a;
142
144
  const content = yield app.vault.read(file);
143
- const { generateZettelId } = yield import("./generate");
144
- const { generateUniqueFilePath } = yield import("./file-utils");
145
145
  const parentPath = ((_a = file.parent) === null || _a === void 0 ? void 0 : _a.path) || "";
146
146
  const baseNameWithoutZettel = file.basename.replace(/-\d{14}$/, "");
147
147
  const zettelId = generateZettelId();
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-operations.js","sourceRoot":"","sources":["../../src/file/file-operations.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { type App, Notice, TFile } from \"obsidian\";\nimport { generateZettelId } from \"../core\";\nimport { generateUniqueFilePath } from \"./file\";\nimport { extractFilePathFromLink } from \"./link-parser\";\n\nexport const fromRoot = (relativePath: string): string => {\n\treturn path.resolve(__dirname, `../../../${relativePath}`);\n};\n\nexport const getActiveFileOrThrow = (app: App): TFile => {\n\tconst activeFile: TFile | null = app.workspace.getActiveFile();\n\tif (!activeFile) {\n\t\tnew Notice(`⚠️ Open a note first.`);\n\t\tthrow new Error(`Open a note first.`);\n\t}\n\treturn activeFile;\n};\n\nexport const getTemplateContent = async (app: App, templatePath: string): Promise<string> => {\n\tconst templateFile = app.vault.getAbstractFileByPath(templatePath);\n\tif (!templateFile) {\n\t\tnew Notice(`❌ Template not found: ${templatePath}`);\n\t\tthrow new Error(`Template not found: ${templatePath}`);\n\t}\n\n\treturn await app.vault.read(templateFile as TFile);\n};\n\nexport const ensureFolderExists = async (app: App, folderPath: string): Promise<void> => {\n\tif (!app.vault.getAbstractFileByPath(folderPath)) {\n\t\tawait app.vault.createFolder(folderPath).catch(() => {});\n\t}\n};\n\nexport const openFileInNewLeaf = async (app: App, file: TFile): Promise<void> => {\n\tawait app.workspace.getLeaf(true).openFile(file);\n};\n\nexport const getNoteFilesFromDir = async (directoryPath: string): Promise<string[]> => {\n\tconst files = await fs.readdir(directoryPath);\n\tconst directoryName = path.basename(directoryPath);\n\n\treturn files.filter((file) => {\n\t\tif (!file.endsWith(\".md\")) return false;\n\n\t\tconst fileNameWithoutExt = path.parse(file).name;\n\t\tif (fileNameWithoutExt === directoryName) {\n\t\t\tconsole.log(`⏭️ Skipping directory-level file: ${file}`);\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t});\n};\n\nexport const getTargetFileFromLink = (app: App, relationshipLink: string): TFile | null => {\n\tconst targetFilePath = extractFilePathFromLink(relationshipLink);\n\tif (!targetFilePath) {\n\t\tconsole.warn(`Failed to extract file path from link: ${relationshipLink}`);\n\t\treturn null;\n\t}\n\n\tconst targetFile = app.vault.getAbstractFileByPath(targetFilePath) as TFile;\n\tif (!targetFile) {\n\t\tconsole.warn(`Target file not found for link: ${relationshipLink}`);\n\t\treturn null;\n\t}\n\n\treturn targetFile;\n};\n\nexport const createFileLink = (file: TFile): string => {\n\tconst folder = file.parent?.path && file.parent.path !== \"/\" ? file.parent.path : \"\";\n\treturn folder ? `[[${folder}/${file.basename}|${file.basename}]]` : `[[${file.basename}]]`;\n};\n\nexport const normalizeArray = (value: string | string[] | undefined): string[] => {\n\tif (!value) {\n\t\treturn [];\n\t}\n\tif (typeof value === \"string\") {\n\t\treturn [value];\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value;\n\t}\n\treturn [];\n};\n\nexport const arraysEqual = (a: string[], b: string[]): boolean => {\n\treturn a.length === b.length && a.every((val, index) => val === b[index]);\n};\n\n/**\n * Normalizes frontmatter content by converting quoted numeric _ZettelIDs to numbers.\n * This handles edge cases where YAML parsers treat numeric strings inconsistently.\n */\nexport const normalizeContent = (content: string): string => {\n\tlet normalized = content;\n\tlet hasChanges = false;\n\n\t// Normalize _ZettelID: \"string\" → number (remove quotes)\n\tconst zettelIdMatch = normalized.match(/^_ZettelID:\\s*\"(\\d+)\"/m);\n\tif (zettelIdMatch) {\n\t\tconst [fullMatch, numericId] = zettelIdMatch;\n\t\tconst replacement = `_ZettelID: ${numericId}`;\n\t\tnormalized = normalized.replace(fullMatch, replacement);\n\t\thasChanges = true;\n\t\tconsole.log(` ✅ _ZettelID: \"${numericId}\" → ${numericId}`);\n\t}\n\n\treturn hasChanges ? normalized : content;\n};\n\n/**\n * Safely performs a file operation with error handling and file validation.\n * Reduces boilerplate for common file operations.\n */\nexport const withFileOperation = async <T>(\n\tapp: App,\n\tevent: any,\n\toperation: (file: TFile) => Promise<T>,\n\terrorMessage: string = \"Operation failed\"\n): Promise<T | null> => {\n\ttry {\n\t\tconst filePath = event.extendedProps.filePath;\n\t\tconst file = app.vault.getAbstractFileByPath(filePath);\n\n\t\tif (!(file instanceof TFile)) {\n\t\t\tnew Notice(\"Could not find the file\");\n\t\t\treturn null;\n\t\t}\n\n\t\treturn await operation(file);\n\t} catch (error) {\n\t\tconsole.error(`Error in file operation:`, error);\n\t\tnew Notice(errorMessage);\n\t\treturn null;\n\t}\n};\n\n/**\n * Safely performs a file operation by file path with error handling and file validation.\n */\nexport const withFile = async <T>(\n\tapp: App,\n\tfilePath: string,\n\toperation: (file: TFile) => Promise<T>,\n\terrorMessage: string = \"Operation failed\"\n): Promise<T | null> => {\n\ttry {\n\t\tconst file = app.vault.getAbstractFileByPath(filePath);\n\n\t\tif (!(file instanceof TFile)) {\n\t\t\tnew Notice(\"Could not find the file\");\n\t\t\treturn null;\n\t\t}\n\n\t\treturn await operation(file);\n\t} catch (error) {\n\t\tconsole.error(`Error in file operation:`, error);\n\t\tnew Notice(errorMessage);\n\t\treturn null;\n\t}\n};\n\n/**\n * Duplicates a file with a new ZettelID, preserving the original content\n * but updating the ZettelID in frontmatter if configured.\n */\nexport const duplicateFileWithNewZettelId = async (\n\tapp: App,\n\tfile: TFile,\n\tzettelIdProp?: string\n): Promise<TFile> => {\n\tconst content = await app.vault.read(file);\n\n\tconst parentPath = file.parent?.path || \"\";\n\tconst baseNameWithoutZettel = file.basename.replace(/-\\d{14}$/, \"\");\n\tconst zettelId = generateZettelId();\n\tconst newBasename = `${baseNameWithoutZettel}-${zettelId}`;\n\tconst newFilePath = generateUniqueFilePath(app, parentPath, newBasename);\n\n\t// Create the new file with original content\n\tconst newFile = await app.vault.create(newFilePath, content);\n\n\t// Update the ZettelID in frontmatter if configured\n\tif (zettelIdProp) {\n\t\tawait app.fileManager.processFrontMatter(newFile, (fm) => {\n\t\t\tfm[zettelIdProp] = zettelId;\n\t\t});\n\t}\n\n\treturn newFile;\n};\n"]}
@@ -0,0 +1,263 @@
1
+ import type { App, CachedMetadata } from "obsidian";
2
+ import { TFile } from "obsidian";
3
+ /**
4
+ * Retrieves a TFile object from the vault by its path.
5
+ * Handles path normalization using Obsidian's normalizePath utility.
6
+ *
7
+ * **Important**: Obsidian file paths ALWAYS include the `.md` extension.
8
+ * The TFile.path property returns paths like "folder/file.md", not "folder/file".
9
+ *
10
+ * @param app - The Obsidian App instance
11
+ * @param filePath - Path to the file (will be normalized, should include .md extension)
12
+ * @returns TFile if found, null otherwise
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // Correct: Include .md extension
17
+ * const file = getFileByPath(app, "folder/note.md");
18
+ *
19
+ * // For wikilinks without extension, add .md
20
+ * const linkPath = "MyNote";
21
+ * const file = getFileByPath(app, `${linkPath}.md`);
22
+ * ```
23
+ */
24
+ export declare function getFileByPath(app: App, filePath: string): TFile | null;
25
+ /**
26
+ * Ensures a file path includes the .md extension.
27
+ * Use this when working with wikilinks or user input that may omit extensions.
28
+ *
29
+ * @param path - File path that may or may not include .md extension
30
+ * @returns Path guaranteed to end with .md
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * ensureMarkdownExtension("MyNote") // "MyNote.md"
35
+ * ensureMarkdownExtension("MyNote.md") // "MyNote.md"
36
+ * ensureMarkdownExtension("folder/note") // "folder/note.md"
37
+ * ```
38
+ */
39
+ export declare function ensureMarkdownExtension(path: string): string;
40
+ /**
41
+ * Removes the .md extension from a file path if present.
42
+ * Useful for displaying file names or creating wikilinks.
43
+ *
44
+ * @param path - File path that may include .md extension
45
+ * @returns Path without .md extension
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * removeMarkdownExtension("folder/note.md") // "folder/note"
50
+ * removeMarkdownExtension("folder/note") // "folder/note"
51
+ * ```
52
+ */
53
+ export declare function removeMarkdownExtension(path: string): string;
54
+ /**
55
+ * Extracts the display name from a file path or wiki link.
56
+ *
57
+ * Handles various formats:
58
+ * - `[[path/to/file|Alias]]` -> returns "Alias"
59
+ * - `[[path/to/file]]` -> returns "file"
60
+ * - `path/to/file.md` -> returns "file"
61
+ * - `file.md` -> returns "file"
62
+ *
63
+ * @param input - File path or wiki link string
64
+ * @returns The display name to show in the UI
65
+ */
66
+ export declare function extractDisplayName(input: string): string;
67
+ /**
68
+ * Extracts the actual file path from a wiki link or returns the path as-is.
69
+ *
70
+ * Handles:
71
+ * - `[[path/to/file|Alias]]` -> returns "path/to/file.md"
72
+ * - `[[path/to/file]]` -> returns "path/to/file.md"
73
+ * - `path/to/file.md` -> returns "path/to/file.md"
74
+ *
75
+ * @param input - File path or wiki link string
76
+ * @returns The actual file path (with .md extension)
77
+ */
78
+ export declare function extractFilePath(input: string): string;
79
+ export interface FileContext {
80
+ path: string;
81
+ pathWithExt: string;
82
+ baseName: string;
83
+ file: TFile | null;
84
+ frontmatter: Record<string, any> | undefined;
85
+ cache: CachedMetadata | null;
86
+ }
87
+ /**
88
+ * Creates a comprehensive file context object containing all relevant file information.
89
+ * Handles path normalization, file lookup, and metadata caching.
90
+ */
91
+ export declare function getFileContext(app: App, path: string): FileContext;
92
+ /**
93
+ * Helper function to work with file context that automatically handles file not found cases.
94
+ * Returns null if the file doesn't exist, otherwise executes the callback with the context.
95
+ */
96
+ export declare function withFileContext<T>(app: App, path: string, callback: (context: FileContext) => Promise<T> | T): Promise<T | null>;
97
+ /**
98
+ * Generates a unique file path by appending a counter if the file already exists.
99
+ * Automatically adds .md extension if not present.
100
+ *
101
+ * @param app - The Obsidian App instance
102
+ * @param folder - Folder path (empty string for root, no trailing slash needed)
103
+ * @param baseName - Base file name without extension
104
+ * @returns Unique file path that doesn't exist in the vault
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * // If "MyNote.md" exists, returns "MyNote 1.md"
109
+ * const path = getUniqueFilePath(app, "", "MyNote");
110
+ *
111
+ * // With folder: "Projects/Task.md" -> "Projects/Task 1.md"
112
+ * const path = getUniqueFilePath(app, "Projects", "Task");
113
+ *
114
+ * // Root folder handling
115
+ * const path = getUniqueFilePath(app, "/", "Note"); // -> "Note.md"
116
+ * ```
117
+ */
118
+ export declare function getUniqueFilePath(app: App, folder: string, baseName: string): string;
119
+ /**
120
+ * Generates a unique file path by appending a counter if the file already exists.
121
+ * Supports custom file extensions.
122
+ *
123
+ * @param app - The Obsidian App instance
124
+ * @param folder - Folder path (empty string for root)
125
+ * @param baseName - Base file name without extension
126
+ * @param extension - File extension (defaults to "md")
127
+ * @returns Unique file path that doesn't exist in the vault
128
+ */
129
+ export declare const generateUniqueFilePath: (app: App, folder: string, baseName: string, extension?: string) => string;
130
+ /**
131
+ * Checks if a file is a folder note.
132
+ * A folder note is a file whose name matches its parent folder name.
133
+ *
134
+ * @param filePath - Path to the file (e.g., "tasks/tasks.md")
135
+ * @returns true if the file is a folder note, false otherwise
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * isFolderNote("tasks/tasks.md") // true
140
+ * isFolderNote("tasks/subtask.md") // false
141
+ * isFolderNote("note.md") // false (no parent folder)
142
+ * isFolderNote("projects/docs/docs.md") // true
143
+ * ```
144
+ */
145
+ export declare function isFolderNote(filePath: string): boolean;
146
+ /**
147
+ * Gets the folder path for a file.
148
+ *
149
+ * @param filePath - Path to the file (e.g., "tasks/subtask.md")
150
+ * @returns Folder path without trailing slash, or empty string if file is in root
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * getFolderPath("tasks/subtask.md") // "tasks"
155
+ * getFolderPath("projects/docs/notes.md") // "projects/docs"
156
+ * getFolderPath("note.md") // ""
157
+ * ```
158
+ */
159
+ export declare function getFolderPath(filePath: string): string;
160
+ /**
161
+ * Gets all markdown files in a specific folder (non-recursive).
162
+ *
163
+ * @param app - The Obsidian App instance
164
+ * @param folderPath - Path to the folder (e.g., "tasks")
165
+ * @returns Array of TFile objects in the folder
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * const files = getFilesInFolder(app, "tasks");
170
+ * // Returns [task1.md, task2.md, tasks.md] but not tasks/subtasks/file.md
171
+ * ```
172
+ */
173
+ export declare function getFilesInFolder(app: App, folderPath: string): TFile[];
174
+ /**
175
+ * Gets all markdown files in a folder and its subfolders recursively.
176
+ *
177
+ * @param app - The Obsidian App instance
178
+ * @param folderPath - Path to the folder (e.g., "tasks")
179
+ * @returns Array of TFile objects in the folder tree
180
+ *
181
+ * @example
182
+ * ```ts
183
+ * const files = getAllFilesInFolderTree(app, "tasks");
184
+ * // Returns all .md files in tasks/ and all its subdirectories
185
+ * ```
186
+ */
187
+ export declare function getAllFilesInFolderTree(app: App, folderPath: string): TFile[];
188
+ /**
189
+ * Gets the parent file path based on folder structure.
190
+ * For a file in a folder, the parent is the folder note if it exists.
191
+ *
192
+ * @param app - The Obsidian App instance
193
+ * @param filePath - Path to the file
194
+ * @returns Path to parent file, or null if no parent exists
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * // If tasks/tasks.md exists
199
+ * getParentByFolder(app, "tasks/subtask.md") // "tasks/tasks.md"
200
+ *
201
+ * // If parent folder note doesn't exist
202
+ * getParentByFolder(app, "tasks/subtask.md") // null
203
+ *
204
+ * // Root level file
205
+ * getParentByFolder(app, "note.md") // null
206
+ * ```
207
+ */
208
+ export declare function getParentByFolder(app: App, filePath: string): string | null;
209
+ /**
210
+ * Gets all child file paths based on folder structure.
211
+ * Works for both folder notes and regular files.
212
+ *
213
+ * For folder notes (e.g., "tasks/tasks.md"):
214
+ * - Returns all files directly in the folder (excluding the folder note)
215
+ * - Includes subfolder notes one level down
216
+ *
217
+ * For regular files (e.g., "tasks/task1.md"):
218
+ * - Returns the folder note from matching subfolder if it exists (e.g., "tasks/task1/task1.md")
219
+ *
220
+ * @param app - The Obsidian App instance
221
+ * @param filePath - Path to the file
222
+ * @returns Array of child file paths
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * // For tasks/tasks.md (folder note)
227
+ * getChildrenByFolder(app, "tasks/tasks.md")
228
+ * // Returns ["tasks/task1.md", "tasks/task2.md", "tasks/subtasks/subtasks.md"]
229
+ *
230
+ * // For tasks/task1.md (regular file with matching subfolder)
231
+ * getChildrenByFolder(app, "tasks/task1.md")
232
+ * // Returns ["tasks/task1/task1.md"] if it exists
233
+ * ```
234
+ */
235
+ export declare function getChildrenByFolder(app: App, filePath: string): string[];
236
+ /**
237
+ * Finds all root nodes in a folder tree.
238
+ * Root nodes are files at the top level of the folder (directly in the folder, not in subfolders).
239
+ *
240
+ * @param app - The Obsidian App instance
241
+ * @param folderPath - Path to the folder
242
+ * @returns Array of root file paths
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * // For folder structure:
247
+ * // tasks/
248
+ * // tasks.md (folder note)
249
+ * // task1.md
250
+ * // subtasks/
251
+ * // subtasks.md
252
+ * // subtask1.md
253
+ *
254
+ * findRootNodesInFolder(app, "tasks")
255
+ * // Returns ["tasks/tasks.md", "tasks/task1.md"]
256
+ * // Excludes subtasks/subtasks.md and subtasks/subtask1.md (they're in subfolder)
257
+ * ```
258
+ */
259
+ export declare function findRootNodesInFolder(app: App, folderPath: string): string[];
260
+ export declare const sanitizeForFilename: (input: string) => string;
261
+ export declare const getFilenameFromPath: (filePath: string) => string;
262
+ export declare const isFileInConfiguredDirectory: (filePath: string, directory: string) => boolean;
263
+ //# sourceMappingURL=file.d.ts.map