@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":"frontmatter-diff.d.ts","sourceRoot":"","sources":["../../src/file/frontmatter-diff.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAElD,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;CAC7C;AAED,MAAM,WAAW,eAAe;IAC/B,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CACjC,cAAc,EAAE,WAAW,EAC3B,cAAc,EAAE,WAAW,EAC3B,YAAY,GAAE,GAAG,CAAC,MAAM,CAAa,GACnC,eAAe,CAwDjB;AAkCD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,eAAe,CA8C/E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAkBxE"}
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Compares two frontmatter objects and returns a detailed diff.
3
+ * Excludes specified properties from comparison (e.g., Prisma-managed properties).
4
+ *
5
+ * @param oldFrontmatter - The original frontmatter
6
+ * @param newFrontmatter - The updated frontmatter
7
+ * @param excludeProps - Set of property keys to exclude from comparison
8
+ * @returns Detailed diff with categorized changes
9
+ */
10
+ export function compareFrontmatter(oldFrontmatter, newFrontmatter, excludeProps = new Set()) {
11
+ const changes = [];
12
+ const added = [];
13
+ const modified = [];
14
+ const deleted = [];
15
+ const allKeys = new Set([...Object.keys(oldFrontmatter), ...Object.keys(newFrontmatter)]);
16
+ for (const key of allKeys) {
17
+ if (excludeProps.has(key)) {
18
+ continue;
19
+ }
20
+ const oldValue = oldFrontmatter[key];
21
+ const newValue = newFrontmatter[key];
22
+ if (!(key in oldFrontmatter) && key in newFrontmatter) {
23
+ const change = {
24
+ key,
25
+ oldValue: undefined,
26
+ newValue,
27
+ changeType: "added",
28
+ };
29
+ changes.push(change);
30
+ added.push(change);
31
+ }
32
+ else if (key in oldFrontmatter && !(key in newFrontmatter)) {
33
+ const change = {
34
+ key,
35
+ oldValue,
36
+ newValue: undefined,
37
+ changeType: "deleted",
38
+ };
39
+ changes.push(change);
40
+ deleted.push(change);
41
+ }
42
+ else if (!deepEqual(oldValue, newValue)) {
43
+ const change = {
44
+ key,
45
+ oldValue,
46
+ newValue,
47
+ changeType: "modified",
48
+ };
49
+ changes.push(change);
50
+ modified.push(change);
51
+ }
52
+ }
53
+ return {
54
+ hasChanges: changes.length > 0,
55
+ changes,
56
+ added,
57
+ modified,
58
+ deleted,
59
+ };
60
+ }
61
+ /**
62
+ * Deep equality check for frontmatter values.
63
+ * Handles primitives, arrays, and objects.
64
+ */
65
+ function deepEqual(a, b) {
66
+ if (a === b)
67
+ return true;
68
+ if (a === null || b === null || a === undefined || b === undefined) {
69
+ return a === b;
70
+ }
71
+ if (typeof a !== typeof b)
72
+ return false;
73
+ if (Array.isArray(a) && Array.isArray(b)) {
74
+ if (a.length !== b.length)
75
+ return false;
76
+ return a.every((val, idx) => deepEqual(val, b[idx]));
77
+ }
78
+ if (typeof a === "object" && typeof b === "object") {
79
+ const keysA = Object.keys(a);
80
+ const keysB = Object.keys(b);
81
+ if (keysA.length !== keysB.length)
82
+ return false;
83
+ return keysA.every((key) => deepEqual(a[key], b[key]));
84
+ }
85
+ return false;
86
+ }
87
+ /**
88
+ * Merges multiple frontmatter diffs into a single accumulated diff.
89
+ * Later diffs override earlier ones for the same key.
90
+ *
91
+ * @param diffs - Array of diffs to merge (in chronological order)
92
+ * @returns A single merged diff containing all accumulated changes
93
+ */
94
+ export function mergeFrontmatterDiffs(diffs) {
95
+ if (diffs.length === 0) {
96
+ return {
97
+ hasChanges: false,
98
+ changes: [],
99
+ added: [],
100
+ modified: [],
101
+ deleted: [],
102
+ };
103
+ }
104
+ if (diffs.length === 1) {
105
+ return diffs[0];
106
+ }
107
+ const changesByKey = new Map();
108
+ for (const diff of diffs) {
109
+ for (const change of diff.changes) {
110
+ const existing = changesByKey.get(change.key);
111
+ if (!existing) {
112
+ changesByKey.set(change.key, Object.assign({}, change));
113
+ }
114
+ else {
115
+ existing.newValue = change.newValue;
116
+ existing.changeType = change.changeType;
117
+ if (existing.oldValue === change.newValue) {
118
+ changesByKey.delete(change.key);
119
+ }
120
+ }
121
+ }
122
+ }
123
+ const allChanges = Array.from(changesByKey.values());
124
+ const added = allChanges.filter((c) => c.changeType === "added");
125
+ const modified = allChanges.filter((c) => c.changeType === "modified");
126
+ const deleted = allChanges.filter((c) => c.changeType === "deleted");
127
+ return {
128
+ hasChanges: allChanges.length > 0,
129
+ changes: allChanges,
130
+ added,
131
+ modified,
132
+ deleted,
133
+ };
134
+ }
135
+ /**
136
+ * Formats a frontmatter change for display in a modal.
137
+ * Returns a human-readable string describing the change.
138
+ */
139
+ export function formatChangeForDisplay(change) {
140
+ const formatValue = (value) => {
141
+ if (value === undefined)
142
+ return "(not set)";
143
+ if (value === null)
144
+ return "null";
145
+ if (typeof value === "string")
146
+ return `"${value}"`;
147
+ if (typeof value === "object")
148
+ return JSON.stringify(value);
149
+ if (typeof value === "number" || typeof value === "boolean")
150
+ return String(value);
151
+ return JSON.stringify(value);
152
+ };
153
+ switch (change.changeType) {
154
+ case "added":
155
+ return `+ ${change.key}: ${formatValue(change.newValue)}`;
156
+ case "deleted":
157
+ return `- ${change.key}: ${formatValue(change.oldValue)}`;
158
+ case "modified":
159
+ return `~ ${change.key}: ${formatValue(change.oldValue)} → ${formatValue(change.newValue)}`;
160
+ }
161
+ }
162
+ //# sourceMappingURL=frontmatter-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter-diff.js","sourceRoot":"","sources":["../../src/file/frontmatter-diff.ts"],"names":[],"mappings":"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","sourcesContent":["export type Frontmatter = Record<string, unknown>;\n\nexport interface FrontmatterChange {\n\tkey: string;\n\toldValue: unknown;\n\tnewValue: unknown;\n\tchangeType: \"added\" | \"modified\" | \"deleted\";\n}\n\nexport interface FrontmatterDiff {\n\thasChanges: boolean;\n\tchanges: FrontmatterChange[];\n\tadded: FrontmatterChange[];\n\tmodified: FrontmatterChange[];\n\tdeleted: FrontmatterChange[];\n}\n\n/**\n * Compares two frontmatter objects and returns a detailed diff.\n * Excludes specified properties from comparison (e.g., Prisma-managed properties).\n *\n * @param oldFrontmatter - The original frontmatter\n * @param newFrontmatter - The updated frontmatter\n * @param excludeProps - Set of property keys to exclude from comparison\n * @returns Detailed diff with categorized changes\n */\nexport function compareFrontmatter(\n\toldFrontmatter: Frontmatter,\n\tnewFrontmatter: Frontmatter,\n\texcludeProps: Set<string> = new Set()\n): FrontmatterDiff {\n\tconst changes: FrontmatterChange[] = [];\n\tconst added: FrontmatterChange[] = [];\n\tconst modified: FrontmatterChange[] = [];\n\tconst deleted: FrontmatterChange[] = [];\n\n\tconst allKeys = new Set([...Object.keys(oldFrontmatter), ...Object.keys(newFrontmatter)]);\n\n\tfor (const key of allKeys) {\n\t\tif (excludeProps.has(key)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst oldValue = oldFrontmatter[key];\n\t\tconst newValue = newFrontmatter[key];\n\n\t\tif (!(key in oldFrontmatter) && key in newFrontmatter) {\n\t\t\tconst change: FrontmatterChange = {\n\t\t\t\tkey,\n\t\t\t\toldValue: undefined,\n\t\t\t\tnewValue,\n\t\t\t\tchangeType: \"added\",\n\t\t\t};\n\n\t\t\tchanges.push(change);\n\t\t\tadded.push(change);\n\t\t} else if (key in oldFrontmatter && !(key in newFrontmatter)) {\n\t\t\tconst change: FrontmatterChange = {\n\t\t\t\tkey,\n\t\t\t\toldValue,\n\t\t\t\tnewValue: undefined,\n\t\t\t\tchangeType: \"deleted\",\n\t\t\t};\n\n\t\t\tchanges.push(change);\n\t\t\tdeleted.push(change);\n\t\t} else if (!deepEqual(oldValue, newValue)) {\n\t\t\tconst change: FrontmatterChange = {\n\t\t\t\tkey,\n\t\t\t\toldValue,\n\t\t\t\tnewValue,\n\t\t\t\tchangeType: \"modified\",\n\t\t\t};\n\n\t\t\tchanges.push(change);\n\t\t\tmodified.push(change);\n\t\t}\n\t}\n\n\treturn {\n\t\thasChanges: changes.length > 0,\n\t\tchanges,\n\t\tadded,\n\t\tmodified,\n\t\tdeleted,\n\t};\n}\n\n/**\n * Deep equality check for frontmatter values.\n * Handles primitives, arrays, and objects.\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n\tif (a === b) return true;\n\n\tif (a === null || b === null || a === undefined || b === undefined) {\n\t\treturn a === b;\n\t}\n\n\tif (typeof a !== typeof b) return false;\n\n\tif (Array.isArray(a) && Array.isArray(b)) {\n\t\tif (a.length !== b.length) return false;\n\t\treturn a.every((val, idx) => deepEqual(val, b[idx]));\n\t}\n\n\tif (typeof a === \"object\" && typeof b === \"object\") {\n\t\tconst keysA = Object.keys(a as Record<string, unknown>);\n\t\tconst keysB = Object.keys(b as Record<string, unknown>);\n\n\t\tif (keysA.length !== keysB.length) return false;\n\n\t\treturn keysA.every((key) =>\n\t\t\tdeepEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key])\n\t\t);\n\t}\n\n\treturn false;\n}\n\n/**\n * Merges multiple frontmatter diffs into a single accumulated diff.\n * Later diffs override earlier ones for the same key.\n *\n * @param diffs - Array of diffs to merge (in chronological order)\n * @returns A single merged diff containing all accumulated changes\n */\nexport function mergeFrontmatterDiffs(diffs: FrontmatterDiff[]): FrontmatterDiff {\n\tif (diffs.length === 0) {\n\t\treturn {\n\t\t\thasChanges: false,\n\t\t\tchanges: [],\n\t\t\tadded: [],\n\t\t\tmodified: [],\n\t\t\tdeleted: [],\n\t\t};\n\t}\n\n\tif (diffs.length === 1) {\n\t\treturn diffs[0];\n\t}\n\n\tconst changesByKey = new Map<string, FrontmatterChange>();\n\n\tfor (const diff of diffs) {\n\t\tfor (const change of diff.changes) {\n\t\t\tconst existing = changesByKey.get(change.key);\n\n\t\t\tif (!existing) {\n\t\t\t\tchangesByKey.set(change.key, { ...change });\n\t\t\t} else {\n\t\t\t\texisting.newValue = change.newValue;\n\t\t\t\texisting.changeType = change.changeType;\n\n\t\t\t\tif (existing.oldValue === change.newValue) {\n\t\t\t\t\tchangesByKey.delete(change.key);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tconst allChanges = Array.from(changesByKey.values());\n\tconst added = allChanges.filter((c) => c.changeType === \"added\");\n\tconst modified = allChanges.filter((c) => c.changeType === \"modified\");\n\tconst deleted = allChanges.filter((c) => c.changeType === \"deleted\");\n\n\treturn {\n\t\thasChanges: allChanges.length > 0,\n\t\tchanges: allChanges,\n\t\tadded,\n\t\tmodified,\n\t\tdeleted,\n\t};\n}\n\n/**\n * Formats a frontmatter change for display in a modal.\n * Returns a human-readable string describing the change.\n */\nexport function formatChangeForDisplay(change: FrontmatterChange): string {\n\tconst formatValue = (value: unknown): string => {\n\t\tif (value === undefined) return \"(not set)\";\n\t\tif (value === null) return \"null\";\n\t\tif (typeof value === \"string\") return `\"${value}\"`;\n\t\tif (typeof value === \"object\") return JSON.stringify(value);\n\t\tif (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n\t\treturn JSON.stringify(value);\n\t};\n\n\tswitch (change.changeType) {\n\t\tcase \"added\":\n\t\t\treturn `+ ${change.key}: ${formatValue(change.newValue)}`;\n\t\tcase \"deleted\":\n\t\t\treturn `- ${change.key}: ${formatValue(change.oldValue)}`;\n\t\tcase \"modified\":\n\t\t\treturn `~ ${change.key}: ${formatValue(change.oldValue)} → ${formatValue(change.newValue)}`;\n\t}\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { App } from "obsidian";
2
+ import type { Frontmatter, FrontmatterDiff } from "./frontmatter-diff";
3
+ export declare function applyFrontmatterChanges(app: App, targetPath: string, sourceFrontmatter: Frontmatter, diff: FrontmatterDiff): Promise<void>;
4
+ //# sourceMappingURL=frontmatter-propagation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter-propagation.d.ts","sourceRoot":"","sources":["../../src/file/frontmatter-propagation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEvE,wBAAsB,uBAAuB,CAC5C,GAAG,EAAE,GAAG,EACR,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,WAAW,EAC9B,IAAI,EAAE,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CAwBf"}
@@ -0,0 +1,28 @@
1
+ import { __awaiter } from "tslib";
2
+ import { TFile } from "obsidian";
3
+ export function applyFrontmatterChanges(app, targetPath, sourceFrontmatter, diff) {
4
+ return __awaiter(this, void 0, void 0, function* () {
5
+ try {
6
+ const file = app.vault.getAbstractFileByPath(targetPath);
7
+ if (!(file instanceof TFile)) {
8
+ console.warn(`Target file not found: ${targetPath}`);
9
+ return;
10
+ }
11
+ yield app.fileManager.processFrontMatter(file, (fm) => {
12
+ for (const change of diff.added) {
13
+ fm[change.key] = sourceFrontmatter[change.key];
14
+ }
15
+ for (const change of diff.modified) {
16
+ fm[change.key] = sourceFrontmatter[change.key];
17
+ }
18
+ for (const change of diff.deleted) {
19
+ delete fm[change.key];
20
+ }
21
+ });
22
+ }
23
+ catch (error) {
24
+ console.error(`Error applying frontmatter changes to ${targetPath}:`, error);
25
+ }
26
+ });
27
+ }
28
+ //# sourceMappingURL=frontmatter-propagation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter-propagation.js","sourceRoot":"","sources":["../../src/file/frontmatter-propagation.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAGjC,MAAM,UAAgB,uBAAuB,CAC5C,GAAQ,EACR,UAAkB,EAClB,iBAA8B,EAC9B,IAAqB;;QAErB,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC;YACzD,IAAI,CAAC,CAAC,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,CAAC,IAAI,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAC;gBACrD,OAAO;YACR,CAAC;YAED,MAAM,GAAG,CAAC,WAAW,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;gBACrD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBACjC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAChD,CAAC;gBAED,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACpC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAChD,CAAC;gBAED,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACnC,OAAO,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,CAAC;YACF,CAAC,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,yCAAyC,UAAU,GAAG,EAAE,KAAK,CAAC,CAAC;QAC9E,CAAC;IACF,CAAC;CAAA","sourcesContent":["import type { App } from \"obsidian\";\nimport { TFile } from \"obsidian\";\nimport type { Frontmatter, FrontmatterDiff } from \"./frontmatter-diff\";\n\nexport async function applyFrontmatterChanges(\n\tapp: App,\n\ttargetPath: string,\n\tsourceFrontmatter: Frontmatter,\n\tdiff: FrontmatterDiff\n): Promise<void> {\n\ttry {\n\t\tconst file = app.vault.getAbstractFileByPath(targetPath);\n\t\tif (!(file instanceof TFile)) {\n\t\t\tconsole.warn(`Target file not found: ${targetPath}`);\n\t\t\treturn;\n\t\t}\n\n\t\tawait app.fileManager.processFrontMatter(file, (fm) => {\n\t\t\tfor (const change of diff.added) {\n\t\t\t\tfm[change.key] = sourceFrontmatter[change.key];\n\t\t\t}\n\n\t\t\tfor (const change of diff.modified) {\n\t\t\t\tfm[change.key] = sourceFrontmatter[change.key];\n\t\t\t}\n\n\t\t\tfor (const change of diff.deleted) {\n\t\t\t\tdelete fm[change.key];\n\t\t\t}\n\t\t});\n\t} catch (error) {\n\t\tconsole.error(`Error applying frontmatter changes to ${targetPath}:`, error);\n\t}\n}\n"]}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Creates file content with YAML frontmatter and body content.
3
+ * This is the atomic file creation format that prevents race conditions.
4
+ *
5
+ * @param frontmatter - Frontmatter as JSON object
6
+ * @param content - Body content (markdown text after frontmatter)
7
+ * @returns Complete file content with YAML frontmatter
8
+ */
9
+ export declare function createFileContentWithFrontmatter(frontmatter: Record<string, unknown>, content?: string): string;
10
+ /**
11
+ * Parses file content to extract frontmatter and body separately.
12
+ * Returns both the frontmatter object and the body content.
13
+ *
14
+ * @param fileContent - Complete file content including frontmatter
15
+ * @returns Object with frontmatter and body
16
+ */
17
+ export declare function parseFileContent(fileContent: string): {
18
+ frontmatter: Record<string, unknown>;
19
+ body: string;
20
+ };
21
+ //# sourceMappingURL=frontmatter-serialization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter-serialization.d.ts","sourceRoot":"","sources":["../../src/file/frontmatter-serialization.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC/C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,SAAK,GACV,MAAM,CAgCR;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG;IACtD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;CACb,CAcA"}
@@ -0,0 +1,57 @@
1
+ import { stringify as stringifyYAML } from "yaml";
2
+ /**
3
+ * Creates file content with YAML frontmatter and body content.
4
+ * This is the atomic file creation format that prevents race conditions.
5
+ *
6
+ * @param frontmatter - Frontmatter as JSON object
7
+ * @param content - Body content (markdown text after frontmatter)
8
+ * @returns Complete file content with YAML frontmatter
9
+ */
10
+ export function createFileContentWithFrontmatter(frontmatter, content = "") {
11
+ if (!frontmatter || Object.keys(frontmatter).length === 0) {
12
+ // No frontmatter, just return content
13
+ return content;
14
+ }
15
+ // Use the yaml library to stringify frontmatter
16
+ // This handles all edge cases: special characters, multiline strings, arrays, nested objects, etc.
17
+ const yaml = stringifyYAML(frontmatter, {
18
+ // Use 2-space indentation (Obsidian standard)
19
+ indent: 2,
20
+ // Don't add document markers (--- at the end)
21
+ lineWidth: 0,
22
+ // Minimize unnecessary quotes
23
+ defaultStringType: "PLAIN",
24
+ // Handle null values explicitly
25
+ nullStr: "",
26
+ }).trim();
27
+ if (!yaml) {
28
+ // Empty frontmatter after stringification
29
+ return content;
30
+ }
31
+ // Ensure content doesn't start with extra newlines
32
+ const trimmedContent = content.replace(/^\n+/, "");
33
+ if (trimmedContent) {
34
+ return `---\n${yaml}\n---\n\n${trimmedContent}`;
35
+ }
36
+ return `---\n${yaml}\n---\n`;
37
+ }
38
+ /**
39
+ * Parses file content to extract frontmatter and body separately.
40
+ * Returns both the frontmatter object and the body content.
41
+ *
42
+ * @param fileContent - Complete file content including frontmatter
43
+ * @returns Object with frontmatter and body
44
+ */
45
+ export function parseFileContent(fileContent) {
46
+ const frontmatterRegex = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/;
47
+ const match = fileContent.match(frontmatterRegex);
48
+ if (!match) {
49
+ // No frontmatter found
50
+ return { frontmatter: {}, body: fileContent };
51
+ }
52
+ const [, , body] = match;
53
+ // For this use case, we just need to split the file
54
+ // The frontmatter will be properly parsed when we read it back with Obsidian's APIs
55
+ return { frontmatter: {}, body: body.trim() };
56
+ }
57
+ //# sourceMappingURL=frontmatter-serialization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter-serialization.js","sourceRoot":"","sources":["../../src/file/frontmatter-serialization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,UAAU,gCAAgC,CAC/C,WAAoC,EACpC,OAAO,GAAG,EAAE;IAEZ,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3D,sCAAsC;QACtC,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,gDAAgD;IAChD,mGAAmG;IACnG,MAAM,IAAI,GAAG,aAAa,CAAC,WAAW,EAAE;QACvC,8CAA8C;QAC9C,MAAM,EAAE,CAAC;QACT,8CAA8C;QAC9C,SAAS,EAAE,CAAC;QACZ,8BAA8B;QAC9B,iBAAiB,EAAE,OAAO;QAC1B,gCAAgC;QAChC,OAAO,EAAE,EAAE;KACX,CAAC,CAAC,IAAI,EAAE,CAAC;IAEV,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,0CAA0C;QAC1C,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,mDAAmD;IACnD,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAEnD,IAAI,cAAc,EAAE,CAAC;QACpB,OAAO,QAAQ,IAAI,YAAY,cAAc,EAAE,CAAC;IACjD,CAAC;IAED,OAAO,QAAQ,IAAI,SAAS,CAAC;AAC9B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAInD,MAAM,gBAAgB,GAAG,oCAAoC,CAAC;IAC9D,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAElD,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,uBAAuB;QACvB,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,CAAC,EAAE,AAAD,EAAG,IAAI,CAAC,GAAG,KAAK,CAAC;IAEzB,oDAAoD;IACpD,oFAAoF;IACpF,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;AAC/C,CAAC","sourcesContent":["import { stringify as stringifyYAML } from \"yaml\";\n\n/**\n * Creates file content with YAML frontmatter and body content.\n * This is the atomic file creation format that prevents race conditions.\n *\n * @param frontmatter - Frontmatter as JSON object\n * @param content - Body content (markdown text after frontmatter)\n * @returns Complete file content with YAML frontmatter\n */\nexport function createFileContentWithFrontmatter(\n\tfrontmatter: Record<string, unknown>,\n\tcontent = \"\"\n): string {\n\tif (!frontmatter || Object.keys(frontmatter).length === 0) {\n\t\t// No frontmatter, just return content\n\t\treturn content;\n\t}\n\n\t// Use the yaml library to stringify frontmatter\n\t// This handles all edge cases: special characters, multiline strings, arrays, nested objects, etc.\n\tconst yaml = stringifyYAML(frontmatter, {\n\t\t// Use 2-space indentation (Obsidian standard)\n\t\tindent: 2,\n\t\t// Don't add document markers (--- at the end)\n\t\tlineWidth: 0,\n\t\t// Minimize unnecessary quotes\n\t\tdefaultStringType: \"PLAIN\",\n\t\t// Handle null values explicitly\n\t\tnullStr: \"\",\n\t}).trim();\n\n\tif (!yaml) {\n\t\t// Empty frontmatter after stringification\n\t\treturn content;\n\t}\n\n\t// Ensure content doesn't start with extra newlines\n\tconst trimmedContent = content.replace(/^\\n+/, \"\");\n\n\tif (trimmedContent) {\n\t\treturn `---\\n${yaml}\\n---\\n\\n${trimmedContent}`;\n\t}\n\n\treturn `---\\n${yaml}\\n---\\n`;\n}\n\n/**\n * Parses file content to extract frontmatter and body separately.\n * Returns both the frontmatter object and the body content.\n *\n * @param fileContent - Complete file content including frontmatter\n * @returns Object with frontmatter and body\n */\nexport function parseFileContent(fileContent: string): {\n\tfrontmatter: Record<string, unknown>;\n\tbody: string;\n} {\n\tconst frontmatterRegex = /^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/;\n\tconst match = fileContent.match(frontmatterRegex);\n\n\tif (!match) {\n\t\t// No frontmatter found\n\t\treturn { frontmatter: {}, body: fileContent };\n\t}\n\n\tconst [, , body] = match;\n\n\t// For this use case, we just need to split the file\n\t// The frontmatter will be properly parsed when we read it back with Obsidian's APIs\n\treturn { frontmatter: {}, body: body.trim() };\n}\n"]}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Serializes a frontmatter value to a string representation for display in input fields.
3
+ * Converts arrays, objects, booleans, and numbers to their string representations.
4
+ */
5
+ export declare function serializeFrontmatterValue(value: unknown): string;
6
+ /**
7
+ * Parses a string value back to its original frontmatter type.
8
+ * Detects and converts to: arrays, objects, booleans, numbers, or keeps as string.
9
+ */
10
+ export declare function parseFrontmatterValue(stringValue: string): unknown;
11
+ /**
12
+ * Converts a record of string values back to their original frontmatter types.
13
+ */
14
+ export declare function parseFrontmatterRecord(record: Record<string, string>): Record<string, unknown>;
15
+ //# sourceMappingURL=frontmatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/file/frontmatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAkBhE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAsClE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQ9F"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Serializes a frontmatter value to a string representation for display in input fields.
3
+ * Converts arrays, objects, booleans, and numbers to their string representations.
4
+ */
5
+ export function serializeFrontmatterValue(value) {
6
+ if (value === null || value === undefined) {
7
+ return "";
8
+ }
9
+ if (typeof value === "string") {
10
+ return value;
11
+ }
12
+ if (typeof value === "number" || typeof value === "boolean") {
13
+ return String(value);
14
+ }
15
+ if (Array.isArray(value) || typeof value === "object") {
16
+ return JSON.stringify(value);
17
+ }
18
+ return String(value);
19
+ }
20
+ /**
21
+ * Parses a string value back to its original frontmatter type.
22
+ * Detects and converts to: arrays, objects, booleans, numbers, or keeps as string.
23
+ */
24
+ export function parseFrontmatterValue(stringValue) {
25
+ // Empty string
26
+ if (stringValue === "") {
27
+ return "";
28
+ }
29
+ // Try to parse as JSON (arrays, objects, null)
30
+ if ((stringValue.startsWith("[") && stringValue.endsWith("]")) ||
31
+ (stringValue.startsWith("{") && stringValue.endsWith("}")) ||
32
+ stringValue === "null") {
33
+ try {
34
+ return JSON.parse(stringValue);
35
+ }
36
+ catch (_a) {
37
+ // If JSON parse fails, return as string
38
+ return stringValue;
39
+ }
40
+ }
41
+ // Parse booleans
42
+ if (stringValue === "true") {
43
+ return true;
44
+ }
45
+ if (stringValue === "false") {
46
+ return false;
47
+ }
48
+ // Parse numbers (including integers and floats)
49
+ if (/^-?\d+(\.\d+)?$/.test(stringValue)) {
50
+ const num = Number(stringValue);
51
+ if (!Number.isNaN(num)) {
52
+ return num;
53
+ }
54
+ }
55
+ // Return as string if no other type matches
56
+ return stringValue;
57
+ }
58
+ /**
59
+ * Converts a record of string values back to their original frontmatter types.
60
+ */
61
+ export function parseFrontmatterRecord(record) {
62
+ const parsed = {};
63
+ for (const [key, value] of Object.entries(record)) {
64
+ parsed[key] = parseFrontmatterValue(value);
65
+ }
66
+ return parsed;
67
+ }
68
+ //# sourceMappingURL=frontmatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/file/frontmatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAAc;IACvD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC3C,OAAO,EAAE,CAAC;IACX,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACxD,eAAe;IACf,IAAI,WAAW,KAAK,EAAE,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACX,CAAC;IAED,+CAA+C;IAC/C,IACC,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1D,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1D,WAAW,KAAK,MAAM,EACrB,CAAC;QACF,IAAI,CAAC;YACJ,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAChC,CAAC;QAAC,WAAM,CAAC;YACR,wCAAwC;YACxC,OAAO,WAAW,CAAC;QACpB,CAAC;IACF,CAAC;IAED,iBAAiB;IACjB,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,gDAAgD;IAChD,IAAI,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,GAAG,CAAC;QACZ,CAAC;IACF,CAAC;IAED,4CAA4C;IAC5C,OAAO,WAAW,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAA8B;IACpE,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC","sourcesContent":["/**\n * Serializes a frontmatter value to a string representation for display in input fields.\n * Converts arrays, objects, booleans, and numbers to their string representations.\n */\nexport function serializeFrontmatterValue(value: unknown): string {\n\tif (value === null || value === undefined) {\n\t\treturn \"\";\n\t}\n\n\tif (typeof value === \"string\") {\n\t\treturn value;\n\t}\n\n\tif (typeof value === \"number\" || typeof value === \"boolean\") {\n\t\treturn String(value);\n\t}\n\n\tif (Array.isArray(value) || typeof value === \"object\") {\n\t\treturn JSON.stringify(value);\n\t}\n\n\treturn String(value);\n}\n\n/**\n * Parses a string value back to its original frontmatter type.\n * Detects and converts to: arrays, objects, booleans, numbers, or keeps as string.\n */\nexport function parseFrontmatterValue(stringValue: string): unknown {\n\t// Empty string\n\tif (stringValue === \"\") {\n\t\treturn \"\";\n\t}\n\n\t// Try to parse as JSON (arrays, objects, null)\n\tif (\n\t\t(stringValue.startsWith(\"[\") && stringValue.endsWith(\"]\")) ||\n\t\t(stringValue.startsWith(\"{\") && stringValue.endsWith(\"}\")) ||\n\t\tstringValue === \"null\"\n\t) {\n\t\ttry {\n\t\t\treturn JSON.parse(stringValue);\n\t\t} catch {\n\t\t\t// If JSON parse fails, return as string\n\t\t\treturn stringValue;\n\t\t}\n\t}\n\n\t// Parse booleans\n\tif (stringValue === \"true\") {\n\t\treturn true;\n\t}\n\tif (stringValue === \"false\") {\n\t\treturn false;\n\t}\n\n\t// Parse numbers (including integers and floats)\n\tif (/^-?\\d+(\\.\\d+)?$/.test(stringValue)) {\n\t\tconst num = Number(stringValue);\n\t\tif (!Number.isNaN(num)) {\n\t\t\treturn num;\n\t\t}\n\t}\n\n\t// Return as string if no other type matches\n\treturn stringValue;\n}\n\n/**\n * Converts a record of string values back to their original frontmatter types.\n */\nexport function parseFrontmatterRecord(record: Record<string, string>): Record<string, unknown> {\n\tconst parsed: Record<string, unknown> = {};\n\n\tfor (const [key, value] of Object.entries(record)) {\n\t\tparsed[key] = parseFrontmatterValue(value);\n\t}\n\n\treturn parsed;\n}\n"]}
@@ -0,0 +1,13 @@
1
+ export * from "./child-reference";
2
+ export * from "./file";
3
+ export * from "./file-operations";
4
+ export * from "./file-utils";
5
+ export * from "./frontmatter";
6
+ export * from "./frontmatter-diff";
7
+ export * from "./frontmatter-propagation";
8
+ export * from "./frontmatter-serialization";
9
+ export * from "./link-parser";
10
+ export * from "./property-utils";
11
+ export * from "./templater";
12
+ export * from "./templater-service";
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/file/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,13 @@
1
+ export * from "./child-reference";
2
+ export * from "./file";
3
+ export * from "./file-operations";
4
+ export * from "./file-utils";
5
+ export * from "./frontmatter";
6
+ export * from "./frontmatter-diff";
7
+ export * from "./frontmatter-propagation";
8
+ export * from "./frontmatter-serialization";
9
+ export * from "./link-parser";
10
+ export * from "./property-utils";
11
+ export * from "./templater";
12
+ export * from "./templater-service";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/file/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC","sourcesContent":["export * from \"./child-reference\";\nexport * from \"./file\";\nexport * from \"./file-operations\";\nexport * from \"./file-utils\";\nexport * from \"./frontmatter\";\nexport * from \"./frontmatter-diff\";\nexport * from \"./frontmatter-propagation\";\nexport * from \"./frontmatter-serialization\";\nexport * from \"./link-parser\";\nexport * from \"./property-utils\";\nexport * from \"./templater\";\nexport * from \"./templater-service\";\n"]}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Handles different link formats and edge cases:
3
+ * [[FileName]] -> FileName.md
4
+ * [[Folder/FileName]] -> Folder/FileName.md
5
+ * [[Folder/FileName|DisplayName]] -> Folder/FileName.md
6
+ * Normalizes paths and handles malformed links gracefully.
7
+ */
8
+ export declare const extractFilePathFromLink: (link: string) => string | null;
9
+ /**
10
+ * Parses an Obsidian wiki link to extract the file path.
11
+ * Handles formats like:
12
+ * - [[path/to/file]]
13
+ * - [[path/to/file|Display Name]]
14
+ *
15
+ * @param link - The wiki link string
16
+ * @returns The file path without the [[ ]] brackets, or null if invalid
17
+ */
18
+ export declare function parseWikiLink(link: string): string | null;
19
+ /**
20
+ * Parses a property value that can be a single link or an array of links.
21
+ * Extracts file paths from all valid wiki links.
22
+ *
23
+ * @param value - The property value (string, string[], or undefined)
24
+ * @returns Array of file paths, empty if no valid links found
25
+ */
26
+ export declare function parsePropertyLinks(value: string | string[] | undefined): string[];
27
+ /**
28
+ * Formats a file path as an Obsidian wiki link with display name.
29
+ * Example: "Projects/MyProject" -> "[[Projects/MyProject|MyProject]]"
30
+ *
31
+ * @param filePath - The file path to format
32
+ * @returns The formatted wiki link with display name alias
33
+ */
34
+ export declare function formatWikiLink(filePath: string): string;
35
+ /**
36
+ * Represents a parsed Obsidian link with its components
37
+ */
38
+ export interface ObsidianLink {
39
+ raw: string;
40
+ path: string;
41
+ alias: string;
42
+ }
43
+ /**
44
+ * Checks if a value is an Obsidian internal link in the format [[...]]
45
+ */
46
+ export declare function isObsidianLink(value: unknown): boolean;
47
+ /**
48
+ * Parses an Obsidian internal link and extracts its components
49
+ *
50
+ * Supports both formats:
51
+ * - Simple: [[Page Name]]
52
+ * - With alias: [[Path/To/Page|Display Name]]
53
+ */
54
+ export declare function parseObsidianLink(linkString: string): ObsidianLink | null;
55
+ /**
56
+ * Gets the display alias from an Obsidian link
57
+ */
58
+ export declare function getObsidianLinkAlias(linkString: string): string;
59
+ /**
60
+ * Gets the file path from an Obsidian link
61
+ */
62
+ export declare function getObsidianLinkPath(linkString: string): string;
63
+ //# sourceMappingURL=link-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-parser.d.ts","sourceRoot":"","sources":["../../src/file/link-parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,KAAG,MAAM,GAAG,IAU/D,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAezD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,CAQjF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAqBvD;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAItD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CA4BzE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAG9D"}