@real1ty-obsidian-plugins/utils 2.30.0 → 2.32.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 (238) hide show
  1. package/dist/async/async.d.ts +69 -0
  2. package/dist/async/async.d.ts.map +1 -0
  3. package/dist/async/async.js +108 -0
  4. package/dist/async/async.js.map +1 -0
  5. package/dist/async/batch-operations.d.ts +21 -0
  6. package/dist/async/batch-operations.d.ts.map +1 -0
  7. package/dist/async/batch-operations.js +60 -0
  8. package/dist/async/batch-operations.js.map +1 -0
  9. package/dist/async/change-notifier.d.ts +13 -0
  10. package/dist/async/change-notifier.d.ts.map +1 -0
  11. package/dist/async/change-notifier.js +26 -0
  12. package/dist/async/change-notifier.js.map +1 -0
  13. package/dist/async/debounced-notifier.d.ts +26 -0
  14. package/dist/async/debounced-notifier.d.ts.map +1 -0
  15. package/dist/async/debounced-notifier.js +50 -0
  16. package/dist/async/debounced-notifier.js.map +1 -0
  17. package/dist/async/index.d.ts +5 -0
  18. package/dist/async/index.d.ts.map +1 -0
  19. package/dist/async/index.js +5 -0
  20. package/dist/async/index.js.map +1 -0
  21. package/dist/components/frontmatter-propagation-modal.d.ts +17 -0
  22. package/dist/components/frontmatter-propagation-modal.d.ts.map +1 -0
  23. package/dist/components/frontmatter-propagation-modal.js +85 -0
  24. package/dist/components/frontmatter-propagation-modal.js.map +1 -0
  25. package/dist/components/index.d.ts +5 -0
  26. package/dist/components/index.d.ts.map +1 -0
  27. package/dist/components/index.js +5 -0
  28. package/dist/components/index.js.map +1 -0
  29. package/dist/components/input-managers/base.d.ts +30 -0
  30. package/dist/components/input-managers/base.d.ts.map +1 -0
  31. package/dist/components/input-managers/base.js +115 -0
  32. package/dist/components/input-managers/base.js.map +1 -0
  33. package/dist/components/input-managers/expression.d.ts +12 -0
  34. package/dist/components/input-managers/expression.d.ts.map +1 -0
  35. package/dist/components/input-managers/expression.js +56 -0
  36. package/dist/components/input-managers/expression.js.map +1 -0
  37. package/dist/components/input-managers/index.d.ts +4 -0
  38. package/dist/components/input-managers/index.d.ts.map +1 -0
  39. package/dist/components/input-managers/index.js +4 -0
  40. package/dist/components/input-managers/index.js.map +1 -0
  41. package/dist/components/input-managers/search.d.ts +6 -0
  42. package/dist/components/input-managers/search.d.ts.map +1 -0
  43. package/dist/components/input-managers/search.js +16 -0
  44. package/dist/components/input-managers/search.js.map +1 -0
  45. package/dist/components/registered-events-component.d.ts +30 -0
  46. package/dist/components/registered-events-component.d.ts.map +1 -0
  47. package/dist/components/registered-events-component.js +43 -0
  48. package/dist/components/registered-events-component.js.map +1 -0
  49. package/dist/components/whats-new-modal.d.ts +315 -0
  50. package/dist/components/whats-new-modal.d.ts.map +1 -0
  51. package/dist/components/whats-new-modal.js +426 -0
  52. package/dist/components/whats-new-modal.js.map +1 -0
  53. package/dist/core/color-utils.d.ts +17 -0
  54. package/dist/core/color-utils.d.ts.map +1 -0
  55. package/dist/core/color-utils.js +29 -0
  56. package/dist/core/color-utils.js.map +1 -0
  57. package/dist/core/css-utils.d.ts +39 -0
  58. package/dist/core/css-utils.d.ts.map +1 -0
  59. package/dist/core/css-utils.js +60 -0
  60. package/dist/core/css-utils.js.map +1 -0
  61. package/dist/core/evaluator/base.d.ts +22 -0
  62. package/dist/core/evaluator/base.d.ts.map +1 -0
  63. package/dist/core/evaluator/base.js +67 -0
  64. package/dist/core/evaluator/base.js.map +1 -0
  65. package/dist/core/evaluator/color.d.ts +19 -0
  66. package/dist/core/evaluator/color.d.ts.map +1 -0
  67. package/dist/core/evaluator/color.js +25 -0
  68. package/dist/core/evaluator/color.js.map +1 -0
  69. package/dist/core/evaluator/excluded.d.ts +32 -0
  70. package/dist/core/evaluator/excluded.d.ts.map +1 -0
  71. package/dist/core/evaluator/excluded.js +41 -0
  72. package/dist/core/evaluator/excluded.js.map +1 -0
  73. package/dist/core/evaluator/filter.d.ts +15 -0
  74. package/dist/core/evaluator/filter.d.ts.map +1 -0
  75. package/dist/core/evaluator/filter.js +27 -0
  76. package/dist/core/evaluator/filter.js.map +1 -0
  77. package/dist/core/evaluator/included.d.ts +36 -0
  78. package/dist/core/evaluator/included.d.ts.map +1 -0
  79. package/dist/core/evaluator/included.js +51 -0
  80. package/dist/core/evaluator/included.js.map +1 -0
  81. package/dist/core/evaluator/index.d.ts +6 -0
  82. package/dist/core/evaluator/index.d.ts.map +1 -0
  83. package/dist/core/evaluator/index.js +6 -0
  84. package/dist/core/evaluator/index.js.map +1 -0
  85. package/dist/core/expression-utils.d.ts +17 -0
  86. package/dist/core/expression-utils.d.ts.map +1 -0
  87. package/dist/core/expression-utils.js +40 -0
  88. package/dist/core/expression-utils.js.map +1 -0
  89. package/dist/core/frontmatter-value.d.ts +157 -0
  90. package/dist/core/frontmatter-value.d.ts.map +1 -0
  91. package/dist/core/frontmatter-value.js +417 -0
  92. package/dist/core/frontmatter-value.js.map +1 -0
  93. package/dist/core/generate.d.ts +7 -0
  94. package/dist/core/generate.d.ts.map +1 -0
  95. package/dist/core/generate.js +13 -0
  96. package/dist/core/generate.js.map +1 -0
  97. package/dist/core/history.d.ts +12 -0
  98. package/dist/core/history.d.ts.map +1 -0
  99. package/dist/core/history.js +39 -0
  100. package/dist/core/history.js.map +1 -0
  101. package/dist/core/index.d.ts +11 -0
  102. package/dist/core/index.d.ts.map +1 -0
  103. package/dist/core/index.js +11 -0
  104. package/dist/core/index.js.map +1 -0
  105. package/dist/core/indexer.d.ts +109 -0
  106. package/dist/core/indexer.d.ts.map +1 -0
  107. package/dist/core/indexer.js +185 -0
  108. package/dist/core/indexer.js.map +1 -0
  109. package/dist/core/property-renderer.d.ts +9 -0
  110. package/dist/core/property-renderer.d.ts.map +1 -0
  111. package/dist/core/property-renderer.js +42 -0
  112. package/dist/core/property-renderer.js.map +1 -0
  113. package/dist/core/validation.d.ts +13 -0
  114. package/dist/core/validation.d.ts.map +1 -0
  115. package/dist/core/validation.js +27 -0
  116. package/dist/core/validation.js.map +1 -0
  117. package/dist/date/date-recurrence.d.ts +30 -0
  118. package/dist/date/date-recurrence.d.ts.map +1 -0
  119. package/dist/date/date-recurrence.js +188 -0
  120. package/dist/date/date-recurrence.js.map +1 -0
  121. package/dist/date/date.d.ts +21 -0
  122. package/dist/date/date.d.ts.map +1 -0
  123. package/dist/date/date.js +105 -0
  124. package/dist/date/date.js.map +1 -0
  125. package/dist/date/index.d.ts +3 -0
  126. package/dist/date/index.d.ts.map +1 -0
  127. package/dist/date/index.js +3 -0
  128. package/dist/date/index.js.map +1 -0
  129. package/dist/file/child-reference.d.ts +9 -0
  130. package/dist/file/child-reference.d.ts.map +1 -0
  131. package/dist/file/child-reference.js +57 -0
  132. package/dist/file/child-reference.js.map +1 -0
  133. package/dist/file/file-operations.d.ts +31 -0
  134. package/dist/file/file-operations.d.ts.map +1 -0
  135. package/dist/file/file-operations.js +160 -0
  136. package/dist/file/file-operations.js.map +1 -0
  137. package/dist/file/file-utils.d.ts +33 -0
  138. package/dist/file/file-utils.d.ts.map +1 -0
  139. package/dist/file/file-utils.js +76 -0
  140. package/dist/file/file-utils.js.map +1 -0
  141. package/dist/file/file.d.ts +332 -0
  142. package/dist/file/file.d.ts.map +1 -0
  143. package/dist/file/file.js +559 -0
  144. package/dist/file/file.js.map +1 -0
  145. package/dist/file/frontmatter-diff.d.ts +38 -0
  146. package/dist/file/frontmatter-diff.d.ts.map +1 -0
  147. package/dist/file/frontmatter-diff.js +162 -0
  148. package/dist/file/frontmatter-diff.js.map +1 -0
  149. package/dist/file/frontmatter-propagation.d.ts +4 -0
  150. package/dist/file/frontmatter-propagation.d.ts.map +1 -0
  151. package/dist/file/frontmatter-propagation.js +28 -0
  152. package/dist/file/frontmatter-propagation.js.map +1 -0
  153. package/dist/file/frontmatter-serialization.d.ts +21 -0
  154. package/dist/file/frontmatter-serialization.d.ts.map +1 -0
  155. package/dist/file/frontmatter-serialization.js +57 -0
  156. package/dist/file/frontmatter-serialization.js.map +1 -0
  157. package/dist/file/frontmatter.d.ts +15 -0
  158. package/dist/file/frontmatter.d.ts.map +1 -0
  159. package/dist/file/frontmatter.js +68 -0
  160. package/dist/file/frontmatter.js.map +1 -0
  161. package/dist/file/index.d.ts +13 -0
  162. package/dist/file/index.d.ts.map +1 -0
  163. package/dist/file/index.js +13 -0
  164. package/dist/file/index.js.map +1 -0
  165. package/dist/file/link-parser.d.ts +63 -0
  166. package/dist/file/link-parser.d.ts.map +1 -0
  167. package/dist/file/link-parser.js +137 -0
  168. package/dist/file/link-parser.js.map +1 -0
  169. package/dist/file/property-utils.d.ts +55 -0
  170. package/dist/file/property-utils.d.ts.map +1 -0
  171. package/dist/file/property-utils.js +90 -0
  172. package/dist/file/property-utils.js.map +1 -0
  173. package/dist/file/templater-service.d.ts +16 -0
  174. package/dist/file/templater-service.d.ts.map +1 -0
  175. package/dist/file/templater-service.js +37 -0
  176. package/dist/file/templater-service.js.map +1 -0
  177. package/dist/file/templater.d.ts +28 -0
  178. package/dist/file/templater.d.ts.map +1 -0
  179. package/dist/file/templater.js +126 -0
  180. package/dist/file/templater.js.map +1 -0
  181. package/dist/index.d.ts +9 -0
  182. package/dist/index.d.ts.map +1 -0
  183. package/dist/index.js +17 -0
  184. package/dist/index.js.map +1 -0
  185. package/dist/inputs/index.d.ts +2 -0
  186. package/dist/inputs/index.d.ts.map +1 -0
  187. package/dist/inputs/index.js +2 -0
  188. package/dist/inputs/index.js.map +1 -0
  189. package/dist/inputs/input-filter-manager.d.ts +72 -0
  190. package/dist/inputs/input-filter-manager.d.ts.map +1 -0
  191. package/dist/inputs/input-filter-manager.js +140 -0
  192. package/dist/inputs/input-filter-manager.js.map +1 -0
  193. package/dist/settings/index.d.ts +3 -0
  194. package/dist/settings/index.d.ts.map +1 -0
  195. package/dist/settings/index.js +3 -0
  196. package/dist/settings/index.js.map +1 -0
  197. package/dist/settings/settings-store.d.ts +20 -0
  198. package/dist/settings/settings-store.d.ts.map +1 -0
  199. package/dist/settings/settings-store.js +82 -0
  200. package/dist/settings/settings-store.js.map +1 -0
  201. package/dist/settings/settings-ui-builder.d.ts +74 -0
  202. package/dist/settings/settings-ui-builder.d.ts.map +1 -0
  203. package/dist/settings/settings-ui-builder.js +436 -0
  204. package/dist/settings/settings-ui-builder.js.map +1 -0
  205. package/dist/string/changelog-parser.d.ts +17 -0
  206. package/dist/string/changelog-parser.d.ts.map +1 -0
  207. package/dist/string/changelog-parser.js +77 -0
  208. package/dist/string/changelog-parser.js.map +1 -0
  209. package/dist/string/filename-utils.d.ts +46 -0
  210. package/dist/string/filename-utils.d.ts.map +1 -0
  211. package/dist/string/filename-utils.js +65 -0
  212. package/dist/string/filename-utils.js.map +1 -0
  213. package/dist/string/index.d.ts +4 -0
  214. package/dist/string/index.d.ts.map +1 -0
  215. package/dist/string/index.js +4 -0
  216. package/dist/string/index.js.map +1 -0
  217. package/dist/string/string.d.ts +5 -0
  218. package/dist/string/string.d.ts.map +1 -0
  219. package/dist/string/string.js +25 -0
  220. package/dist/string/string.js.map +1 -0
  221. package/dist/testing/index.d.ts +5 -0
  222. package/dist/testing/index.d.ts.map +1 -0
  223. package/dist/testing/index.js +6 -0
  224. package/dist/testing/index.js.map +1 -0
  225. package/dist/testing/mocks/obsidian.d.ts +150 -0
  226. package/dist/testing/mocks/obsidian.d.ts.map +1 -0
  227. package/dist/testing/mocks/obsidian.js +226 -0
  228. package/dist/testing/mocks/obsidian.js.map +1 -0
  229. package/dist/testing/mocks/utils.d.ts +14 -0
  230. package/dist/testing/mocks/utils.d.ts.map +1 -0
  231. package/dist/testing/mocks/utils.js +85 -0
  232. package/dist/testing/mocks/utils.js.map +1 -0
  233. package/dist/testing/setup.d.ts +2 -0
  234. package/dist/testing/setup.d.ts.map +1 -0
  235. package/dist/testing/setup.js +18 -0
  236. package/dist/testing/setup.js.map +1 -0
  237. package/package.json +1 -1
  238. package/src/components/whats-new-modal.ts +306 -2
@@ -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,12 @@
1
+ type Snapshot<T> = () => T;
2
+ type Restore<T> = (state: T) => void;
3
+ export declare function createHistory<T>(snapshot: Snapshot<T>, restore: Restore<T>): {
4
+ save(): void;
5
+ undo(): T | null;
6
+ redo(): T | null;
7
+ canUndo(): boolean;
8
+ canRedo(): boolean;
9
+ getOriginalState(): T | null;
10
+ };
11
+ export {};
12
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/core/history.ts"],"names":[],"mappings":"AAAA,KAAK,QAAQ,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AAC3B,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;AAErC,wBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YAKjE,IAAI;YAKJ,CAAC,GAAG,IAAI;YAUR,CAAC,GAAG,IAAI;eASL,OAAO;eAIP,OAAO;wBAIE,CAAC,GAAG,IAAI;EAI7B"}
@@ -0,0 +1,39 @@
1
+ export function createHistory(snapshot, restore) {
2
+ const undoStack = [];
3
+ const redoStack = [];
4
+ return {
5
+ save() {
6
+ undoStack.push(snapshot());
7
+ redoStack.length = 0;
8
+ },
9
+ undo() {
10
+ if (undoStack.length < 2)
11
+ return null;
12
+ const current = snapshot();
13
+ redoStack.push(current);
14
+ undoStack.pop(); // Remove current state from undo stack
15
+ const prev = undoStack[undoStack.length - 1]; // Get previous state
16
+ restore(prev);
17
+ return prev;
18
+ },
19
+ redo() {
20
+ if (!redoStack.length)
21
+ return null;
22
+ const current = snapshot();
23
+ undoStack.push(current);
24
+ const next = redoStack.pop();
25
+ restore(next);
26
+ return next;
27
+ },
28
+ canUndo() {
29
+ return undoStack.length > 1;
30
+ },
31
+ canRedo() {
32
+ return redoStack.length > 0;
33
+ },
34
+ getOriginalState() {
35
+ return undoStack.length > 0 ? undoStack[0] : null;
36
+ },
37
+ };
38
+ }
39
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/core/history.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,aAAa,CAAI,QAAqB,EAAE,OAAmB;IAC1E,MAAM,SAAS,GAAQ,EAAE,CAAC;IAC1B,MAAM,SAAS,GAAQ,EAAE,CAAC;IAE1B,OAAO;QACN,IAAI;YACH,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC3B,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QACtB,CAAC;QAED,IAAI;YACH,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;YACtC,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;YAC3B,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACxB,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,uCAAuC;YACxD,MAAM,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB;YACnE,OAAO,CAAC,IAAI,CAAC,CAAC;YACd,OAAO,IAAI,CAAC;QACb,CAAC;QAED,IAAI;YACH,IAAI,CAAC,SAAS,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC;YACnC,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;YAC3B,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACxB,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,EAAG,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,CAAC;YACd,OAAO,IAAI,CAAC;QACb,CAAC;QAED,OAAO;YACN,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QAC7B,CAAC;QAED,OAAO;YACN,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QAC7B,CAAC;QAED,gBAAgB;YACf,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACnD,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["type Snapshot<T> = () => T;\ntype Restore<T> = (state: T) => void;\n\nexport function createHistory<T>(snapshot: Snapshot<T>, restore: Restore<T>) {\n\tconst undoStack: T[] = [];\n\tconst redoStack: T[] = [];\n\n\treturn {\n\t\tsave(): void {\n\t\t\tundoStack.push(snapshot());\n\t\t\tredoStack.length = 0;\n\t\t},\n\n\t\tundo(): T | null {\n\t\t\tif (undoStack.length < 2) return null;\n\t\t\tconst current = snapshot();\n\t\t\tredoStack.push(current);\n\t\t\tundoStack.pop(); // Remove current state from undo stack\n\t\t\tconst prev = undoStack[undoStack.length - 1]; // Get previous state\n\t\t\trestore(prev);\n\t\t\treturn prev;\n\t\t},\n\n\t\tredo(): T | null {\n\t\t\tif (!redoStack.length) return null;\n\t\t\tconst current = snapshot();\n\t\t\tundoStack.push(current);\n\t\t\tconst next = redoStack.pop()!;\n\t\t\trestore(next);\n\t\t\treturn next;\n\t\t},\n\n\t\tcanUndo(): boolean {\n\t\t\treturn undoStack.length > 1;\n\t\t},\n\n\t\tcanRedo(): boolean {\n\t\t\treturn redoStack.length > 0;\n\t\t},\n\n\t\tgetOriginalState(): T | null {\n\t\t\treturn undoStack.length > 0 ? undoStack[0] : null;\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,11 @@
1
+ export * from "./color-utils";
2
+ export * from "./css-utils";
3
+ export * from "./evaluator";
4
+ export * from "./expression-utils";
5
+ export * from "./frontmatter-value";
6
+ export * from "./generate";
7
+ export * from "./history";
8
+ export * from "./indexer";
9
+ export * from "./property-renderer";
10
+ export * from "./validation";
11
+ //# 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,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC"}
@@ -0,0 +1,11 @@
1
+ export * from "./color-utils";
2
+ export * from "./css-utils";
3
+ export * from "./evaluator";
4
+ export * from "./expression-utils";
5
+ export * from "./frontmatter-value";
6
+ export * from "./generate";
7
+ export * from "./history";
8
+ export * from "./indexer";
9
+ export * from "./property-renderer";
10
+ export * from "./validation";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC","sourcesContent":["export * from \"./color-utils\";\nexport * from \"./css-utils\";\nexport * from \"./evaluator\";\nexport * from \"./expression-utils\";\nexport * from \"./frontmatter-value\";\nexport * from \"./generate\";\nexport * from \"./history\";\nexport * from \"./indexer\";\nexport * from \"./property-renderer\";\nexport * from \"./validation\";\n"]}
@@ -0,0 +1,109 @@
1
+ import { type App } from "obsidian";
2
+ import { type BehaviorSubject, type Observable } from "rxjs";
3
+ import { type FrontmatterDiff } from "../file/frontmatter-diff";
4
+ /**
5
+ * Generic frontmatter object type for indexer
6
+ */
7
+ export type IndexerFrontmatter = Record<string, unknown>;
8
+ /**
9
+ * Configuration for the generic indexer
10
+ */
11
+ export interface IndexerConfig {
12
+ /**
13
+ * Function that determines whether a file should be included in the indexer.
14
+ * Returns true if the file should be indexed, false otherwise.
15
+ * If not provided, all files are included.
16
+ */
17
+ includeFile?: (path: string) => boolean;
18
+ /**
19
+ * Properties to exclude when comparing frontmatter diffs
20
+ */
21
+ excludedDiffProps?: Set<string>;
22
+ /**
23
+ * Concurrency limit for file scanning operations
24
+ */
25
+ scanConcurrency?: number;
26
+ /**
27
+ * Debounce time in milliseconds for file change events
28
+ */
29
+ debounceMs?: number;
30
+ }
31
+ /**
32
+ * Raw file source with frontmatter and metadata
33
+ */
34
+ export interface FileSource {
35
+ filePath: string;
36
+ mtime: number;
37
+ frontmatter: IndexerFrontmatter;
38
+ folder: string;
39
+ }
40
+ /**
41
+ * Types of indexer events
42
+ */
43
+ export type IndexerEventType = "file-changed" | "file-deleted";
44
+ /**
45
+ * Generic indexer event
46
+ */
47
+ export interface IndexerEvent {
48
+ type: IndexerEventType;
49
+ filePath: string;
50
+ oldPath?: string;
51
+ source?: FileSource;
52
+ oldFrontmatter?: IndexerFrontmatter;
53
+ frontmatterDiff?: FrontmatterDiff;
54
+ /**
55
+ * True if this deletion event is part of a rename operation.
56
+ * Only present on "file-deleted" events.
57
+ */
58
+ isRename?: boolean;
59
+ }
60
+ /**
61
+ * Generic indexer that listens to Obsidian vault events and emits
62
+ * RxJS observables with frontmatter diffs and metadata.
63
+ *
64
+ * This indexer is framework-agnostic and can be used by any plugin
65
+ * that needs to track file changes with frontmatter.
66
+ */
67
+ export declare class Indexer {
68
+ private config;
69
+ private fileSub;
70
+ private configSubscription;
71
+ private vault;
72
+ private metadataCache;
73
+ private scanEventsSubject;
74
+ private indexingCompleteSubject;
75
+ private frontmatterCache;
76
+ readonly events$: Observable<IndexerEvent>;
77
+ readonly indexingComplete$: Observable<boolean>;
78
+ constructor(app: App, configStore: BehaviorSubject<IndexerConfig>);
79
+ private normalizeConfig;
80
+ start(): Promise<void>;
81
+ stop(): void;
82
+ resync(): void;
83
+ /**
84
+ * Scan all markdown files in the configured directory
85
+ */
86
+ private scanAllFiles;
87
+ /**
88
+ * Create an observable from a vault event
89
+ */
90
+ private fromVaultEvent;
91
+ private static isMarkdownFile;
92
+ /**
93
+ * Filter to only relevant markdown files in configured directory
94
+ */
95
+ private toRelevantFiles;
96
+ /**
97
+ * Debounce events by file path
98
+ */
99
+ private debounceByPath;
100
+ /**
101
+ * Build the file system events observable stream
102
+ */
103
+ private buildFileSystemEvents$;
104
+ /**
105
+ * Build an indexer event from a file
106
+ */
107
+ private buildEvent;
108
+ }
109
+ //# sourceMappingURL=indexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../../src/core/indexer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAA6D,MAAM,UAAU,CAAC;AAC/F,OAAO,EACN,KAAK,eAAe,EAKpB,KAAK,UAAU,EAKf,MAAM,MAAM,CAAC;AAEd,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEpF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAExC;;OAEG;IACH,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAEhC;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,kBAAkB,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,cAAc,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACpC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAQD;;;;;;GAMG;AACH,qBAAa,OAAO;IACnB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,kBAAkB,CAA6B;IACvD,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,uBAAuB,CAAyC;IACxE,OAAO,CAAC,gBAAgB,CAA8C;IAEtE,SAAgB,OAAO,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC;IAClD,SAAgB,iBAAiB,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;gBAE3C,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,eAAe,CAAC,aAAa,CAAC;IAoBjE,OAAO,CAAC,eAAe;IASjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B,IAAI,IAAI,IAAI;IAQZ,MAAM,IAAI,IAAI;IAMd;;OAEG;YACW,YAAY;IA+B1B;;OAEG;IACH,OAAO,CAAC,cAAc;IA6BtB,OAAO,CAAC,MAAM,CAAC,cAAc;IAI7B;;OAEG;IACH,OAAO,CAAC,eAAe;IAQvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAgD9B;;OAEG;YACW,UAAU;CA8BxB"}
@@ -0,0 +1,185 @@
1
+ import { __awaiter } from "tslib";
2
+ import { TFile } from "obsidian";
3
+ import { from, fromEventPattern, lastValueFrom, merge, of, BehaviorSubject as RxBehaviorSubject, Subject, } from "rxjs";
4
+ import { debounceTime, filter, groupBy, map, mergeMap, switchMap, toArray } from "rxjs/operators";
5
+ import { compareFrontmatter } from "../file/frontmatter-diff";
6
+ /**
7
+ * Generic indexer that listens to Obsidian vault events and emits
8
+ * RxJS observables with frontmatter diffs and metadata.
9
+ *
10
+ * This indexer is framework-agnostic and can be used by any plugin
11
+ * that needs to track file changes with frontmatter.
12
+ */
13
+ export class Indexer {
14
+ constructor(app, configStore) {
15
+ this.fileSub = null;
16
+ this.configSubscription = null;
17
+ this.scanEventsSubject = new Subject();
18
+ this.indexingCompleteSubject = new RxBehaviorSubject(false);
19
+ this.frontmatterCache = new Map();
20
+ this.vault = app.vault;
21
+ this.metadataCache = app.metadataCache;
22
+ this.config = this.normalizeConfig(configStore.value);
23
+ this.configSubscription = configStore.subscribe((newConfig) => {
24
+ const includeFileChanged = this.config.includeFile !== this.normalizeConfig(newConfig).includeFile;
25
+ this.config = this.normalizeConfig(newConfig);
26
+ if (includeFileChanged) {
27
+ this.indexingCompleteSubject.next(false);
28
+ void this.scanAllFiles();
29
+ }
30
+ });
31
+ this.events$ = this.scanEventsSubject.asObservable();
32
+ this.indexingComplete$ = this.indexingCompleteSubject.asObservable();
33
+ }
34
+ normalizeConfig(config) {
35
+ return {
36
+ includeFile: config.includeFile || (() => true),
37
+ excludedDiffProps: config.excludedDiffProps || new Set(),
38
+ scanConcurrency: config.scanConcurrency || 10,
39
+ debounceMs: config.debounceMs || 100,
40
+ };
41
+ }
42
+ start() {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ this.indexingCompleteSubject.next(false);
45
+ const fileSystemEvents$ = this.buildFileSystemEvents$();
46
+ this.fileSub = fileSystemEvents$.subscribe((event) => {
47
+ this.scanEventsSubject.next(event);
48
+ });
49
+ yield this.scanAllFiles();
50
+ });
51
+ }
52
+ stop() {
53
+ var _a, _b;
54
+ (_a = this.fileSub) === null || _a === void 0 ? void 0 : _a.unsubscribe();
55
+ this.fileSub = null;
56
+ (_b = this.configSubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
57
+ this.configSubscription = null;
58
+ this.indexingCompleteSubject.complete();
59
+ }
60
+ resync() {
61
+ this.frontmatterCache.clear();
62
+ this.indexingCompleteSubject.next(false);
63
+ void this.scanAllFiles();
64
+ }
65
+ /**
66
+ * Scan all markdown files in the configured directory
67
+ */
68
+ scanAllFiles() {
69
+ return __awaiter(this, void 0, void 0, function* () {
70
+ const allFiles = this.vault.getMarkdownFiles();
71
+ const relevantFiles = allFiles.filter((file) => this.config.includeFile(file.path));
72
+ const events$ = from(relevantFiles).pipe(mergeMap((file) => __awaiter(this, void 0, void 0, function* () {
73
+ try {
74
+ return yield this.buildEvent(file);
75
+ }
76
+ catch (error) {
77
+ console.error(`Error processing file ${file.path}:`, error);
78
+ return null;
79
+ }
80
+ }), this.config.scanConcurrency), filter((event) => event !== null), toArray());
81
+ try {
82
+ const allEvents = yield lastValueFrom(events$);
83
+ for (const event of allEvents) {
84
+ this.scanEventsSubject.next(event);
85
+ }
86
+ this.indexingCompleteSubject.next(true);
87
+ }
88
+ catch (error) {
89
+ console.error("❌ Error during file scanning:", error);
90
+ this.indexingCompleteSubject.next(true);
91
+ }
92
+ });
93
+ }
94
+ /**
95
+ * Create an observable from a vault event
96
+ */
97
+ fromVaultEvent(eventName) {
98
+ if (eventName === "create") {
99
+ return fromEventPattern((handler) => this.vault.on("create", handler), (handler) => this.vault.off("create", handler));
100
+ }
101
+ if (eventName === "modify") {
102
+ return fromEventPattern((handler) => this.vault.on("modify", handler), (handler) => this.vault.off("modify", handler));
103
+ }
104
+ if (eventName === "delete") {
105
+ return fromEventPattern((handler) => this.vault.on("delete", handler), (handler) => this.vault.off("delete", handler));
106
+ }
107
+ // eventName === "rename"
108
+ return fromEventPattern((handler) => this.vault.on("rename", handler), (handler) => this.vault.off("rename", handler)).pipe(map(([file]) => file));
109
+ }
110
+ static isMarkdownFile(f) {
111
+ return f instanceof TFile && f.extension === "md";
112
+ }
113
+ /**
114
+ * Filter to only relevant markdown files in configured directory
115
+ */
116
+ toRelevantFiles() {
117
+ return (source) => source.pipe(filter((f) => Indexer.isMarkdownFile(f)), filter((f) => this.config.includeFile(f.path)));
118
+ }
119
+ /**
120
+ * Debounce events by file path
121
+ */
122
+ debounceByPath(ms, key) {
123
+ return (source) => source.pipe(groupBy(key), mergeMap((g$) => g$.pipe(debounceTime(ms))));
124
+ }
125
+ /**
126
+ * Build the file system events observable stream
127
+ */
128
+ buildFileSystemEvents$() {
129
+ const created$ = this.fromVaultEvent("create").pipe(this.toRelevantFiles());
130
+ const modified$ = this.fromVaultEvent("modify").pipe(this.toRelevantFiles());
131
+ const deleted$ = this.fromVaultEvent("delete").pipe(this.toRelevantFiles());
132
+ const renamed$ = fromEventPattern((handler) => this.vault.on("rename", handler), (handler) => this.vault.off("rename", handler));
133
+ const changedIntents$ = merge(created$, modified$).pipe(this.debounceByPath(this.config.debounceMs, (f) => f.path), map((file) => ({ kind: "changed", file, path: file.path })));
134
+ const deletedIntents$ = deleted$.pipe(map((file) => ({ kind: "deleted", path: file.path })));
135
+ const renamedIntents$ = renamed$.pipe(map(([f, oldPath]) => [f, oldPath]), filter(([f]) => Indexer.isMarkdownFile(f) && this.config.includeFile(f.path)), mergeMap(([f, oldPath]) => [
136
+ { kind: "deleted", path: oldPath, isRename: true },
137
+ { kind: "changed", file: f, path: f.path, oldPath },
138
+ ]));
139
+ const intents$ = merge(changedIntents$, deletedIntents$, renamedIntents$);
140
+ return intents$.pipe(switchMap((intent) => {
141
+ if (intent.kind === "deleted") {
142
+ this.frontmatterCache.delete(intent.path);
143
+ return of({
144
+ type: "file-deleted",
145
+ filePath: intent.path,
146
+ isRename: intent.isRename,
147
+ });
148
+ }
149
+ return from(this.buildEvent(intent.file, intent.oldPath)).pipe(filter((e) => e !== null));
150
+ }));
151
+ }
152
+ /**
153
+ * Build an indexer event from a file
154
+ */
155
+ buildEvent(file, oldPath) {
156
+ return __awaiter(this, void 0, void 0, function* () {
157
+ var _a;
158
+ const cache = this.metadataCache.getFileCache(file);
159
+ if (!cache || !cache.frontmatter)
160
+ return null;
161
+ const { frontmatter } = cache;
162
+ const oldFrontmatter = this.frontmatterCache.get(file.path);
163
+ const source = {
164
+ filePath: file.path,
165
+ mtime: file.stat.mtime,
166
+ frontmatter,
167
+ folder: ((_a = file.parent) === null || _a === void 0 ? void 0 : _a.path) || "",
168
+ };
169
+ const event = {
170
+ type: "file-changed",
171
+ filePath: file.path,
172
+ oldPath,
173
+ source,
174
+ oldFrontmatter,
175
+ frontmatterDiff: oldFrontmatter
176
+ ? compareFrontmatter(oldFrontmatter, frontmatter, this.config.excludedDiffProps)
177
+ : undefined,
178
+ };
179
+ // Update cache
180
+ this.frontmatterCache.set(file.path, Object.assign({}, frontmatter));
181
+ return event;
182
+ });
183
+ }
184
+ }
185
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../../src/core/indexer.ts"],"names":[],"mappings":"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","sourcesContent":["import { type App, type MetadataCache, type TAbstractFile, TFile, type Vault } from \"obsidian\";\nimport {\n\ttype BehaviorSubject,\n\tfrom,\n\tfromEventPattern,\n\tlastValueFrom,\n\tmerge,\n\ttype Observable,\n\tof,\n\tBehaviorSubject as RxBehaviorSubject,\n\tSubject,\n\ttype Subscription,\n} from \"rxjs\";\nimport { debounceTime, filter, groupBy, map, mergeMap, switchMap, toArray } from \"rxjs/operators\";\nimport { compareFrontmatter, type FrontmatterDiff } from \"../file/frontmatter-diff\";\n\n/**\n * Generic frontmatter object type for indexer\n */\nexport type IndexerFrontmatter = Record<string, unknown>;\n\n/**\n * Configuration for the generic indexer\n */\nexport interface IndexerConfig {\n\t/**\n\t * Function that determines whether a file should be included in the indexer.\n\t * Returns true if the file should be indexed, false otherwise.\n\t * If not provided, all files are included.\n\t */\n\tincludeFile?: (path: string) => boolean;\n\n\t/**\n\t * Properties to exclude when comparing frontmatter diffs\n\t */\n\texcludedDiffProps?: Set<string>;\n\n\t/**\n\t * Concurrency limit for file scanning operations\n\t */\n\tscanConcurrency?: number;\n\n\t/**\n\t * Debounce time in milliseconds for file change events\n\t */\n\tdebounceMs?: number;\n}\n\n/**\n * Raw file source with frontmatter and metadata\n */\nexport interface FileSource {\n\tfilePath: string;\n\tmtime: number;\n\tfrontmatter: IndexerFrontmatter;\n\tfolder: string;\n}\n\n/**\n * Types of indexer events\n */\nexport type IndexerEventType = \"file-changed\" | \"file-deleted\";\n\n/**\n * Generic indexer event\n */\nexport interface IndexerEvent {\n\ttype: IndexerEventType;\n\tfilePath: string;\n\toldPath?: string;\n\tsource?: FileSource;\n\toldFrontmatter?: IndexerFrontmatter;\n\tfrontmatterDiff?: FrontmatterDiff;\n\t/**\n\t * True if this deletion event is part of a rename operation.\n\t * Only present on \"file-deleted\" events.\n\t */\n\tisRename?: boolean;\n}\n\ntype VaultEvent = \"create\" | \"modify\" | \"delete\" | \"rename\";\n\ntype FileIntent =\n\t| { kind: \"changed\"; file: TFile; path: string; oldPath?: string }\n\t| { kind: \"deleted\"; path: string; isRename?: boolean };\n\n/**\n * Generic indexer that listens to Obsidian vault events and emits\n * RxJS observables with frontmatter diffs and metadata.\n *\n * This indexer is framework-agnostic and can be used by any plugin\n * that needs to track file changes with frontmatter.\n */\nexport class Indexer {\n\tprivate config: Required<IndexerConfig>;\n\tprivate fileSub: Subscription | null = null;\n\tprivate configSubscription: Subscription | null = null;\n\tprivate vault: Vault;\n\tprivate metadataCache: MetadataCache;\n\tprivate scanEventsSubject = new Subject<IndexerEvent>();\n\tprivate indexingCompleteSubject = new RxBehaviorSubject<boolean>(false);\n\tprivate frontmatterCache: Map<string, IndexerFrontmatter> = new Map();\n\n\tpublic readonly events$: Observable<IndexerEvent>;\n\tpublic readonly indexingComplete$: Observable<boolean>;\n\n\tconstructor(app: App, configStore: BehaviorSubject<IndexerConfig>) {\n\t\tthis.vault = app.vault;\n\t\tthis.metadataCache = app.metadataCache;\n\t\tthis.config = this.normalizeConfig(configStore.value);\n\n\t\tthis.configSubscription = configStore.subscribe((newConfig) => {\n\t\t\tconst includeFileChanged =\n\t\t\t\tthis.config.includeFile !== this.normalizeConfig(newConfig).includeFile;\n\t\t\tthis.config = this.normalizeConfig(newConfig);\n\n\t\t\tif (includeFileChanged) {\n\t\t\t\tthis.indexingCompleteSubject.next(false);\n\t\t\t\tvoid this.scanAllFiles();\n\t\t\t}\n\t\t});\n\n\t\tthis.events$ = this.scanEventsSubject.asObservable();\n\t\tthis.indexingComplete$ = this.indexingCompleteSubject.asObservable();\n\t}\n\n\tprivate normalizeConfig(config: IndexerConfig): Required<IndexerConfig> {\n\t\treturn {\n\t\t\tincludeFile: config.includeFile || (() => true),\n\t\t\texcludedDiffProps: config.excludedDiffProps || new Set(),\n\t\t\tscanConcurrency: config.scanConcurrency || 10,\n\t\t\tdebounceMs: config.debounceMs || 100,\n\t\t};\n\t}\n\n\tasync start(): Promise<void> {\n\t\tthis.indexingCompleteSubject.next(false);\n\n\t\tconst fileSystemEvents$ = this.buildFileSystemEvents$();\n\n\t\tthis.fileSub = fileSystemEvents$.subscribe((event) => {\n\t\t\tthis.scanEventsSubject.next(event);\n\t\t});\n\n\t\tawait this.scanAllFiles();\n\t}\n\n\tstop(): void {\n\t\tthis.fileSub?.unsubscribe();\n\t\tthis.fileSub = null;\n\t\tthis.configSubscription?.unsubscribe();\n\t\tthis.configSubscription = null;\n\t\tthis.indexingCompleteSubject.complete();\n\t}\n\n\tresync(): void {\n\t\tthis.frontmatterCache.clear();\n\t\tthis.indexingCompleteSubject.next(false);\n\t\tvoid this.scanAllFiles();\n\t}\n\n\t/**\n\t * Scan all markdown files in the configured directory\n\t */\n\tprivate async scanAllFiles(): Promise<void> {\n\t\tconst allFiles = this.vault.getMarkdownFiles();\n\t\tconst relevantFiles = allFiles.filter((file) => this.config.includeFile(file.path));\n\n\t\tconst events$ = from(relevantFiles).pipe(\n\t\t\tmergeMap(async (file) => {\n\t\t\t\ttry {\n\t\t\t\t\treturn await this.buildEvent(file);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(`Error processing file ${file.path}:`, error);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}, this.config.scanConcurrency),\n\t\t\tfilter((event): event is IndexerEvent => event !== null),\n\t\t\ttoArray()\n\t\t);\n\n\t\ttry {\n\t\t\tconst allEvents = await lastValueFrom(events$);\n\n\t\t\tfor (const event of allEvents) {\n\t\t\t\tthis.scanEventsSubject.next(event);\n\t\t\t}\n\n\t\t\tthis.indexingCompleteSubject.next(true);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"❌ Error during file scanning:\", error);\n\t\t\tthis.indexingCompleteSubject.next(true);\n\t\t}\n\t}\n\n\t/**\n\t * Create an observable from a vault event\n\t */\n\tprivate fromVaultEvent(eventName: VaultEvent): Observable<TAbstractFile> {\n\t\tif (eventName === \"create\") {\n\t\t\treturn fromEventPattern<TAbstractFile>(\n\t\t\t\t(handler) => this.vault.on(\"create\", handler),\n\t\t\t\t(handler) => this.vault.off(\"create\", handler)\n\t\t\t);\n\t\t}\n\n\t\tif (eventName === \"modify\") {\n\t\t\treturn fromEventPattern<TAbstractFile>(\n\t\t\t\t(handler) => this.vault.on(\"modify\", handler),\n\t\t\t\t(handler) => this.vault.off(\"modify\", handler)\n\t\t\t);\n\t\t}\n\n\t\tif (eventName === \"delete\") {\n\t\t\treturn fromEventPattern<TAbstractFile>(\n\t\t\t\t(handler) => this.vault.on(\"delete\", handler),\n\t\t\t\t(handler) => this.vault.off(\"delete\", handler)\n\t\t\t);\n\t\t}\n\n\t\t// eventName === \"rename\"\n\t\treturn fromEventPattern<[TAbstractFile, string]>(\n\t\t\t(handler) => this.vault.on(\"rename\", handler),\n\t\t\t(handler) => this.vault.off(\"rename\", handler)\n\t\t).pipe(map(([file]) => file));\n\t}\n\n\tprivate static isMarkdownFile(f: TAbstractFile): f is TFile {\n\t\treturn f instanceof TFile && f.extension === \"md\";\n\t}\n\n\t/**\n\t * Filter to only relevant markdown files in configured directory\n\t */\n\tprivate toRelevantFiles<T extends TAbstractFile>() {\n\t\treturn (source: Observable<T>) =>\n\t\t\tsource.pipe(\n\t\t\t\tfilter((f: TAbstractFile): f is TFile => Indexer.isMarkdownFile(f)),\n\t\t\t\tfilter((f) => this.config.includeFile(f.path))\n\t\t\t);\n\t}\n\n\t/**\n\t * Debounce events by file path\n\t */\n\tprivate debounceByPath<T>(ms: number, key: (x: T) => string) {\n\t\treturn (source: Observable<T>) =>\n\t\t\tsource.pipe(\n\t\t\t\tgroupBy(key),\n\t\t\t\tmergeMap((g$) => g$.pipe(debounceTime(ms)))\n\t\t\t);\n\t}\n\n\t/**\n\t * Build the file system events observable stream\n\t */\n\tprivate buildFileSystemEvents$(): Observable<IndexerEvent> {\n\t\tconst created$ = this.fromVaultEvent(\"create\").pipe(this.toRelevantFiles());\n\t\tconst modified$ = this.fromVaultEvent(\"modify\").pipe(this.toRelevantFiles());\n\t\tconst deleted$ = this.fromVaultEvent(\"delete\").pipe(this.toRelevantFiles());\n\n\t\tconst renamed$ = fromEventPattern<[TAbstractFile, string]>(\n\t\t\t(handler) => this.vault.on(\"rename\", handler),\n\t\t\t(handler) => this.vault.off(\"rename\", handler)\n\t\t);\n\n\t\tconst changedIntents$ = merge(created$, modified$).pipe(\n\t\t\tthis.debounceByPath(this.config.debounceMs, (f) => f.path),\n\t\t\tmap((file): FileIntent => ({ kind: \"changed\", file, path: file.path }))\n\t\t);\n\n\t\tconst deletedIntents$ = deleted$.pipe(\n\t\t\tmap((file): FileIntent => ({ kind: \"deleted\", path: file.path }))\n\t\t);\n\n\t\tconst renamedIntents$ = renamed$.pipe(\n\t\t\tmap(([f, oldPath]) => [f, oldPath] as const),\n\t\t\tfilter(([f]) => Indexer.isMarkdownFile(f) && this.config.includeFile(f.path)),\n\t\t\tmergeMap(([f, oldPath]) => [\n\t\t\t\t{ kind: \"deleted\", path: oldPath, isRename: true } as FileIntent,\n\t\t\t\t{ kind: \"changed\", file: f, path: f.path, oldPath } as FileIntent,\n\t\t\t])\n\t\t);\n\n\t\tconst intents$ = merge(changedIntents$, deletedIntents$, renamedIntents$);\n\n\t\treturn intents$.pipe(\n\t\t\tswitchMap((intent) => {\n\t\t\t\tif (intent.kind === \"deleted\") {\n\t\t\t\t\tthis.frontmatterCache.delete(intent.path);\n\t\t\t\t\treturn of<IndexerEvent>({\n\t\t\t\t\t\ttype: \"file-deleted\",\n\t\t\t\t\t\tfilePath: intent.path,\n\t\t\t\t\t\tisRename: intent.isRename,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn from(this.buildEvent(intent.file, intent.oldPath)).pipe(\n\t\t\t\t\tfilter((e): e is IndexerEvent => e !== null)\n\t\t\t\t);\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Build an indexer event from a file\n\t */\n\tprivate async buildEvent(file: TFile, oldPath?: string): Promise<IndexerEvent | null> {\n\t\tconst cache = this.metadataCache.getFileCache(file);\n\t\tif (!cache || !cache.frontmatter) return null;\n\n\t\tconst { frontmatter } = cache;\n\t\tconst oldFrontmatter = this.frontmatterCache.get(file.path);\n\n\t\tconst source: FileSource = {\n\t\t\tfilePath: file.path,\n\t\t\tmtime: file.stat.mtime,\n\t\t\tfrontmatter,\n\t\t\tfolder: file.parent?.path || \"\",\n\t\t};\n\n\t\tconst event: IndexerEvent = {\n\t\t\ttype: \"file-changed\",\n\t\t\tfilePath: file.path,\n\t\t\toldPath,\n\t\t\tsource,\n\t\t\toldFrontmatter,\n\t\t\tfrontmatterDiff: oldFrontmatter\n\t\t\t\t? compareFrontmatter(oldFrontmatter, frontmatter, this.config.excludedDiffProps)\n\t\t\t\t: undefined,\n\t\t};\n\n\t\t// Update cache\n\t\tthis.frontmatterCache.set(file.path, { ...frontmatter });\n\n\t\treturn event;\n\t}\n}\n"]}
@@ -0,0 +1,9 @@
1
+ export interface PropertyRendererConfig {
2
+ createLink: (text: string, path: string, isObsidianLink: boolean) => HTMLElement;
3
+ createText: (text: string) => HTMLElement | Text;
4
+ createSeparator?: () => HTMLElement | Text;
5
+ }
6
+ export declare function renderPropertyValue(container: HTMLElement, value: any, config: PropertyRendererConfig): void;
7
+ export declare function createTextNode(text: string): Text;
8
+ export declare function createDefaultSeparator(): Text;
9
+ //# sourceMappingURL=property-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-renderer.d.ts","sourceRoot":"","sources":["../../src/core/property-renderer.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,sBAAsB;IACtC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,KAAK,WAAW,CAAC;IACjF,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,GAAG,IAAI,CAAC;IACjD,eAAe,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;CAC3C;AAED,wBAAgB,mBAAmB,CAClC,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,sBAAsB,GAC5B,IAAI,CAqBN;AAsBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
@@ -0,0 +1,42 @@
1
+ import { getObsidianLinkAlias, getObsidianLinkPath, isObsidianLink } from "../file/link-parser";
2
+ export function renderPropertyValue(container, value, config) {
3
+ // Handle arrays - render each item separately
4
+ if (Array.isArray(value)) {
5
+ const hasClickableLinks = value.some(isObsidianLink);
6
+ if (hasClickableLinks) {
7
+ for (let index = 0; index < value.length; index++) {
8
+ if (index > 0 && config.createSeparator) {
9
+ container.appendChild(config.createSeparator());
10
+ }
11
+ renderSingleValue(container, value[index], config);
12
+ }
13
+ }
14
+ else {
15
+ // Plain array - just join with commas
16
+ const textNode = config.createText(value.join(", "));
17
+ container.appendChild(textNode);
18
+ }
19
+ return;
20
+ }
21
+ renderSingleValue(container, value, config);
22
+ }
23
+ function renderSingleValue(container, value, config) {
24
+ const stringValue = String(value).trim();
25
+ if (isObsidianLink(stringValue)) {
26
+ const displayText = getObsidianLinkAlias(stringValue);
27
+ const linkPath = getObsidianLinkPath(stringValue);
28
+ const link = config.createLink(displayText, linkPath, true);
29
+ container.appendChild(link);
30
+ return;
31
+ }
32
+ // Regular text
33
+ const textNode = config.createText(stringValue);
34
+ container.appendChild(textNode);
35
+ }
36
+ export function createTextNode(text) {
37
+ return document.createTextNode(text);
38
+ }
39
+ export function createDefaultSeparator() {
40
+ return document.createTextNode(", ");
41
+ }
42
+ //# sourceMappingURL=property-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-renderer.js","sourceRoot":"","sources":["../../src/core/property-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAQhG,MAAM,UAAU,mBAAmB,CAClC,SAAsB,EACtB,KAAU,EACV,MAA8B;IAE9B,8CAA8C;IAC9C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAErD,IAAI,iBAAiB,EAAE,CAAC;YACvB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;gBACnD,IAAI,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;oBACzC,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC;gBACjD,CAAC;gBACD,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;YACpD,CAAC;QACF,CAAC;aAAM,CAAC;YACP,sCAAsC;YACtC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACrD,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;QACD,OAAO;IACR,CAAC;IAED,iBAAiB,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,iBAAiB,CACzB,SAAsB,EACtB,KAAU,EACV,MAA8B;IAE9B,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IAEzC,IAAI,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC;QACjC,MAAM,WAAW,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;QACtD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC5D,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO;IACR,CAAC;IAED,eAAe;IACf,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAChD,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IAC1C,OAAO,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,sBAAsB;IACrC,OAAO,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC","sourcesContent":["import { getObsidianLinkAlias, getObsidianLinkPath, isObsidianLink } from \"../file/link-parser\";\n\nexport interface PropertyRendererConfig {\n\tcreateLink: (text: string, path: string, isObsidianLink: boolean) => HTMLElement;\n\tcreateText: (text: string) => HTMLElement | Text;\n\tcreateSeparator?: () => HTMLElement | Text;\n}\n\nexport function renderPropertyValue(\n\tcontainer: HTMLElement,\n\tvalue: any,\n\tconfig: PropertyRendererConfig\n): void {\n\t// Handle arrays - render each item separately\n\tif (Array.isArray(value)) {\n\t\tconst hasClickableLinks = value.some(isObsidianLink);\n\n\t\tif (hasClickableLinks) {\n\t\t\tfor (let index = 0; index < value.length; index++) {\n\t\t\t\tif (index > 0 && config.createSeparator) {\n\t\t\t\t\tcontainer.appendChild(config.createSeparator());\n\t\t\t\t}\n\t\t\t\trenderSingleValue(container, value[index], config);\n\t\t\t}\n\t\t} else {\n\t\t\t// Plain array - just join with commas\n\t\t\tconst textNode = config.createText(value.join(\", \"));\n\t\t\tcontainer.appendChild(textNode);\n\t\t}\n\t\treturn;\n\t}\n\n\trenderSingleValue(container, value, config);\n}\n\nfunction renderSingleValue(\n\tcontainer: HTMLElement,\n\tvalue: any,\n\tconfig: PropertyRendererConfig\n): void {\n\tconst stringValue = String(value).trim();\n\n\tif (isObsidianLink(stringValue)) {\n\t\tconst displayText = getObsidianLinkAlias(stringValue);\n\t\tconst linkPath = getObsidianLinkPath(stringValue);\n\t\tconst link = config.createLink(displayText, linkPath, true);\n\t\tcontainer.appendChild(link);\n\t\treturn;\n\t}\n\n\t// Regular text\n\tconst textNode = config.createText(stringValue);\n\tcontainer.appendChild(textNode);\n}\n\nexport function createTextNode(text: string): Text {\n\treturn document.createTextNode(text);\n}\n\nexport function createDefaultSeparator(): Text {\n\treturn document.createTextNode(\", \");\n}\n"]}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Checks if a value is not empty.
3
+ * Returns false for: undefined, null, empty string, or empty arrays.
4
+ * Returns true for all other values.
5
+ */
6
+ export declare function isNotEmpty(value: unknown): boolean;
7
+ /**
8
+ * Parses a value to a positive integer.
9
+ * Handles both number and string types from frontmatter.
10
+ * Returns the parsed integer if valid and positive, otherwise returns the fallback value.
11
+ */
12
+ export declare function parsePositiveInt(value: unknown, fallback: number): number;
13
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQlD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMzE"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Checks if a value is not empty.
3
+ * Returns false for: undefined, null, empty string, or empty arrays.
4
+ * Returns true for all other values.
5
+ */
6
+ export function isNotEmpty(value) {
7
+ if (value === undefined || value === null || value === "") {
8
+ return false;
9
+ }
10
+ if (Array.isArray(value) && value.length === 0) {
11
+ return false;
12
+ }
13
+ return true;
14
+ }
15
+ /**
16
+ * Parses a value to a positive integer.
17
+ * Handles both number and string types from frontmatter.
18
+ * Returns the parsed integer if valid and positive, otherwise returns the fallback value.
19
+ */
20
+ export function parsePositiveInt(value, fallback) {
21
+ if (value === undefined || value === null) {
22
+ return fallback;
23
+ }
24
+ const parsed = typeof value === "number" ? Math.floor(value) : Number.parseInt(String(value), 10);
25
+ return !Number.isNaN(parsed) && parsed > 0 ? parsed : fallback;
26
+ }
27
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc;IACxC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QAC3D,OAAO,KAAK,CAAC;IACd,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc,EAAE,QAAgB;IAChE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC3C,OAAO,QAAQ,CAAC;IACjB,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAClG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AAChE,CAAC","sourcesContent":["/**\n * Checks if a value is not empty.\n * Returns false for: undefined, null, empty string, or empty arrays.\n * Returns true for all other values.\n */\nexport function isNotEmpty(value: unknown): boolean {\n\tif (value === undefined || value === null || value === \"\") {\n\t\treturn false;\n\t}\n\tif (Array.isArray(value) && value.length === 0) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Parses a value to a positive integer.\n * Handles both number and string types from frontmatter.\n * Returns the parsed integer if valid and positive, otherwise returns the fallback value.\n */\nexport function parsePositiveInt(value: unknown, fallback: number): number {\n\tif (value === undefined || value === null) {\n\t\treturn fallback;\n\t}\n\tconst parsed = typeof value === \"number\" ? Math.floor(value) : Number.parseInt(String(value), 10);\n\treturn !Number.isNaN(parsed) && parsed > 0 ? parsed : fallback;\n}\n"]}
@@ -0,0 +1,30 @@
1
+ import type { DateTime } from "luxon";
2
+ export type RecurrenceType = "daily" | "weekly" | "bi-weekly" | "monthly" | "bi-monthly" | "yearly";
3
+ export type Weekday = "sunday" | "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday";
4
+ export declare const WEEKDAY_TO_NUMBER: Record<Weekday, number>;
5
+ /**
6
+ * Calculates the next occurrence date based on recurrence type and optional weekdays
7
+ */
8
+ export declare function getNextOccurrence(currentDate: DateTime, recurrenceType: RecurrenceType, weekdays?: Weekday[]): DateTime;
9
+ /**
10
+ * Checks if a given date matches any of the specified weekdays
11
+ */
12
+ export declare function isDateOnWeekdays(date: DateTime, weekdays: Weekday[]): boolean;
13
+ /**
14
+ * Finds the next occurrence on specified weekdays
15
+ */
16
+ export declare function getNextWeekdayOccurrence(currentDate: DateTime, weekdays: Weekday[]): DateTime;
17
+ /**
18
+ * Finds the next bi-weekly occurrence on specified weekdays
19
+ */
20
+ export declare function getNextBiWeeklyOccurrence(currentDate: DateTime, weekdays: Weekday[]): DateTime;
21
+ export declare function iterateOccurrencesInRange(startDate: DateTime, rrules: {
22
+ type: RecurrenceType;
23
+ weekdays?: Weekday[];
24
+ }, rangeStart: DateTime, rangeEnd: DateTime): Generator<DateTime, void, unknown>;
25
+ /**
26
+ * Calculates a DateTime for a specific date with optional time
27
+ */
28
+ export declare function calculateInstanceDateTime(instanceDate: DateTime, timeString?: string): DateTime;
29
+ export declare function calculateRecurringInstanceDateTime(nextInstanceDateTime: DateTime, nodeRecuringEventDateTime: DateTime, recurrenceType: RecurrenceType, allDay?: boolean): DateTime;
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"}