@real1ty-obsidian-plugins/utils 2.28.0 → 2.30.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.
- package/package.json +1 -1
- package/src/core/history.ts +45 -0
- package/src/core/index.ts +1 -0
- package/src/settings/settings-ui-builder.ts +0 -1
- package/dist/async/async.d.ts +0 -69
- package/dist/async/async.d.ts.map +0 -1
- package/dist/async/async.js +0 -108
- package/dist/async/async.js.map +0 -1
- package/dist/async/batch-operations.d.ts +0 -21
- package/dist/async/batch-operations.d.ts.map +0 -1
- package/dist/async/batch-operations.js +0 -60
- package/dist/async/batch-operations.js.map +0 -1
- package/dist/async/change-notifier.d.ts +0 -13
- package/dist/async/change-notifier.d.ts.map +0 -1
- package/dist/async/change-notifier.js +0 -26
- package/dist/async/change-notifier.js.map +0 -1
- package/dist/async/debounced-notifier.d.ts +0 -26
- package/dist/async/debounced-notifier.d.ts.map +0 -1
- package/dist/async/debounced-notifier.js +0 -50
- package/dist/async/debounced-notifier.js.map +0 -1
- package/dist/async/index.d.ts +0 -5
- package/dist/async/index.d.ts.map +0 -1
- package/dist/async/index.js +0 -5
- package/dist/async/index.js.map +0 -1
- package/dist/components/frontmatter-propagation-modal.d.ts +0 -17
- package/dist/components/frontmatter-propagation-modal.d.ts.map +0 -1
- package/dist/components/frontmatter-propagation-modal.js +0 -85
- package/dist/components/frontmatter-propagation-modal.js.map +0 -1
- package/dist/components/index.d.ts +0 -5
- package/dist/components/index.d.ts.map +0 -1
- package/dist/components/index.js +0 -5
- package/dist/components/index.js.map +0 -1
- package/dist/components/input-managers/base.d.ts +0 -30
- package/dist/components/input-managers/base.d.ts.map +0 -1
- package/dist/components/input-managers/base.js +0 -115
- package/dist/components/input-managers/base.js.map +0 -1
- package/dist/components/input-managers/expression.d.ts +0 -12
- package/dist/components/input-managers/expression.d.ts.map +0 -1
- package/dist/components/input-managers/expression.js +0 -56
- package/dist/components/input-managers/expression.js.map +0 -1
- package/dist/components/input-managers/index.d.ts +0 -4
- package/dist/components/input-managers/index.d.ts.map +0 -1
- package/dist/components/input-managers/index.js +0 -4
- package/dist/components/input-managers/index.js.map +0 -1
- package/dist/components/input-managers/search.d.ts +0 -6
- package/dist/components/input-managers/search.d.ts.map +0 -1
- package/dist/components/input-managers/search.js +0 -16
- package/dist/components/input-managers/search.js.map +0 -1
- package/dist/components/registered-events-component.d.ts +0 -30
- package/dist/components/registered-events-component.d.ts.map +0 -1
- package/dist/components/registered-events-component.js +0 -43
- package/dist/components/registered-events-component.js.map +0 -1
- package/dist/components/whats-new-modal.d.ts +0 -64
- package/dist/components/whats-new-modal.d.ts.map +0 -1
- package/dist/components/whats-new-modal.js +0 -139
- package/dist/components/whats-new-modal.js.map +0 -1
- package/dist/core/color-utils.d.ts +0 -17
- package/dist/core/color-utils.d.ts.map +0 -1
- package/dist/core/color-utils.js +0 -29
- package/dist/core/color-utils.js.map +0 -1
- package/dist/core/css-utils.d.ts +0 -39
- package/dist/core/css-utils.d.ts.map +0 -1
- package/dist/core/css-utils.js +0 -60
- package/dist/core/css-utils.js.map +0 -1
- package/dist/core/evaluator/base.d.ts +0 -22
- package/dist/core/evaluator/base.d.ts.map +0 -1
- package/dist/core/evaluator/base.js +0 -67
- package/dist/core/evaluator/base.js.map +0 -1
- package/dist/core/evaluator/color.d.ts +0 -19
- package/dist/core/evaluator/color.d.ts.map +0 -1
- package/dist/core/evaluator/color.js +0 -25
- package/dist/core/evaluator/color.js.map +0 -1
- package/dist/core/evaluator/excluded.d.ts +0 -32
- package/dist/core/evaluator/excluded.d.ts.map +0 -1
- package/dist/core/evaluator/excluded.js +0 -41
- package/dist/core/evaluator/excluded.js.map +0 -1
- package/dist/core/evaluator/filter.d.ts +0 -15
- package/dist/core/evaluator/filter.d.ts.map +0 -1
- package/dist/core/evaluator/filter.js +0 -27
- package/dist/core/evaluator/filter.js.map +0 -1
- package/dist/core/evaluator/included.d.ts +0 -36
- package/dist/core/evaluator/included.d.ts.map +0 -1
- package/dist/core/evaluator/included.js +0 -51
- package/dist/core/evaluator/included.js.map +0 -1
- package/dist/core/evaluator/index.d.ts +0 -6
- package/dist/core/evaluator/index.d.ts.map +0 -1
- package/dist/core/evaluator/index.js +0 -6
- package/dist/core/evaluator/index.js.map +0 -1
- package/dist/core/expression-utils.d.ts +0 -17
- package/dist/core/expression-utils.d.ts.map +0 -1
- package/dist/core/expression-utils.js +0 -40
- package/dist/core/expression-utils.js.map +0 -1
- package/dist/core/frontmatter-value.d.ts +0 -157
- package/dist/core/frontmatter-value.d.ts.map +0 -1
- package/dist/core/frontmatter-value.js +0 -417
- package/dist/core/frontmatter-value.js.map +0 -1
- package/dist/core/generate.d.ts +0 -7
- package/dist/core/generate.d.ts.map +0 -1
- package/dist/core/generate.js +0 -13
- package/dist/core/generate.js.map +0 -1
- package/dist/core/index.d.ts +0 -10
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -10
- package/dist/core/index.js.map +0 -1
- package/dist/core/indexer.d.ts +0 -109
- package/dist/core/indexer.d.ts.map +0 -1
- package/dist/core/indexer.js +0 -185
- package/dist/core/indexer.js.map +0 -1
- package/dist/core/property-renderer.d.ts +0 -9
- package/dist/core/property-renderer.d.ts.map +0 -1
- package/dist/core/property-renderer.js +0 -42
- package/dist/core/property-renderer.js.map +0 -1
- package/dist/core/validation.d.ts +0 -13
- package/dist/core/validation.d.ts.map +0 -1
- package/dist/core/validation.js +0 -27
- package/dist/core/validation.js.map +0 -1
- package/dist/date/date-recurrence.d.ts +0 -30
- package/dist/date/date-recurrence.d.ts.map +0 -1
- package/dist/date/date-recurrence.js +0 -188
- package/dist/date/date-recurrence.js.map +0 -1
- package/dist/date/date.d.ts +0 -21
- package/dist/date/date.d.ts.map +0 -1
- package/dist/date/date.js +0 -105
- package/dist/date/date.js.map +0 -1
- package/dist/date/index.d.ts +0 -3
- package/dist/date/index.d.ts.map +0 -1
- package/dist/date/index.js +0 -3
- package/dist/date/index.js.map +0 -1
- package/dist/file/child-reference.d.ts +0 -9
- package/dist/file/child-reference.d.ts.map +0 -1
- package/dist/file/child-reference.js +0 -57
- package/dist/file/child-reference.js.map +0 -1
- package/dist/file/file-operations.d.ts +0 -31
- package/dist/file/file-operations.d.ts.map +0 -1
- package/dist/file/file-operations.js +0 -160
- package/dist/file/file-operations.js.map +0 -1
- package/dist/file/file-utils.d.ts +0 -33
- package/dist/file/file-utils.d.ts.map +0 -1
- package/dist/file/file-utils.js +0 -76
- package/dist/file/file-utils.js.map +0 -1
- package/dist/file/file.d.ts +0 -332
- package/dist/file/file.d.ts.map +0 -1
- package/dist/file/file.js +0 -559
- package/dist/file/file.js.map +0 -1
- package/dist/file/frontmatter-diff.d.ts +0 -38
- package/dist/file/frontmatter-diff.d.ts.map +0 -1
- package/dist/file/frontmatter-diff.js +0 -162
- package/dist/file/frontmatter-diff.js.map +0 -1
- package/dist/file/frontmatter-propagation.d.ts +0 -4
- package/dist/file/frontmatter-propagation.d.ts.map +0 -1
- package/dist/file/frontmatter-propagation.js +0 -28
- package/dist/file/frontmatter-propagation.js.map +0 -1
- package/dist/file/frontmatter-serialization.d.ts +0 -21
- package/dist/file/frontmatter-serialization.d.ts.map +0 -1
- package/dist/file/frontmatter-serialization.js +0 -57
- package/dist/file/frontmatter-serialization.js.map +0 -1
- package/dist/file/frontmatter.d.ts +0 -15
- package/dist/file/frontmatter.d.ts.map +0 -1
- package/dist/file/frontmatter.js +0 -68
- package/dist/file/frontmatter.js.map +0 -1
- package/dist/file/index.d.ts +0 -13
- package/dist/file/index.d.ts.map +0 -1
- package/dist/file/index.js +0 -13
- package/dist/file/index.js.map +0 -1
- package/dist/file/link-parser.d.ts +0 -63
- package/dist/file/link-parser.d.ts.map +0 -1
- package/dist/file/link-parser.js +0 -137
- package/dist/file/link-parser.js.map +0 -1
- package/dist/file/property-utils.d.ts +0 -55
- package/dist/file/property-utils.d.ts.map +0 -1
- package/dist/file/property-utils.js +0 -90
- package/dist/file/property-utils.js.map +0 -1
- package/dist/file/templater-service.d.ts +0 -16
- package/dist/file/templater-service.d.ts.map +0 -1
- package/dist/file/templater-service.js +0 -37
- package/dist/file/templater-service.js.map +0 -1
- package/dist/file/templater.d.ts +0 -28
- package/dist/file/templater.d.ts.map +0 -1
- package/dist/file/templater.js +0 -126
- package/dist/file/templater.js.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -17
- package/dist/index.js.map +0 -1
- package/dist/inputs/index.d.ts +0 -2
- package/dist/inputs/index.d.ts.map +0 -1
- package/dist/inputs/index.js +0 -2
- package/dist/inputs/index.js.map +0 -1
- package/dist/inputs/input-filter-manager.d.ts +0 -72
- package/dist/inputs/input-filter-manager.d.ts.map +0 -1
- package/dist/inputs/input-filter-manager.js +0 -140
- package/dist/inputs/input-filter-manager.js.map +0 -1
- package/dist/settings/index.d.ts +0 -3
- package/dist/settings/index.d.ts.map +0 -1
- package/dist/settings/index.js +0 -3
- package/dist/settings/index.js.map +0 -1
- package/dist/settings/settings-store.d.ts +0 -20
- package/dist/settings/settings-store.d.ts.map +0 -1
- package/dist/settings/settings-store.js +0 -82
- package/dist/settings/settings-store.js.map +0 -1
- package/dist/settings/settings-ui-builder.d.ts +0 -74
- package/dist/settings/settings-ui-builder.d.ts.map +0 -1
- package/dist/settings/settings-ui-builder.js +0 -437
- package/dist/settings/settings-ui-builder.js.map +0 -1
- package/dist/string/changelog-parser.d.ts +0 -17
- package/dist/string/changelog-parser.d.ts.map +0 -1
- package/dist/string/changelog-parser.js +0 -77
- package/dist/string/changelog-parser.js.map +0 -1
- package/dist/string/filename-utils.d.ts +0 -46
- package/dist/string/filename-utils.d.ts.map +0 -1
- package/dist/string/filename-utils.js +0 -65
- package/dist/string/filename-utils.js.map +0 -1
- package/dist/string/index.d.ts +0 -4
- package/dist/string/index.d.ts.map +0 -1
- package/dist/string/index.js +0 -4
- package/dist/string/index.js.map +0 -1
- package/dist/string/string.d.ts +0 -5
- package/dist/string/string.d.ts.map +0 -1
- package/dist/string/string.js +0 -25
- package/dist/string/string.js.map +0 -1
- package/dist/testing/index.d.ts +0 -5
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js +0 -6
- package/dist/testing/index.js.map +0 -1
- package/dist/testing/mocks/obsidian.d.ts +0 -150
- package/dist/testing/mocks/obsidian.d.ts.map +0 -1
- package/dist/testing/mocks/obsidian.js +0 -226
- package/dist/testing/mocks/obsidian.js.map +0 -1
- package/dist/testing/mocks/utils.d.ts +0 -14
- package/dist/testing/mocks/utils.d.ts.map +0 -1
- package/dist/testing/mocks/utils.js +0 -85
- package/dist/testing/mocks/utils.js.map +0 -1
- package/dist/testing/setup.d.ts +0 -2
- package/dist/testing/setup.d.ts.map +0 -1
- package/dist/testing/setup.js +0 -18
- package/dist/testing/setup.js.map +0 -1
package/dist/core/indexer.js
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
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
|
package/dist/core/indexer.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1,9 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,42 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1,13 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/dist/core/validation.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1,30 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
export const WEEKDAY_TO_NUMBER = {
|
|
2
|
-
sunday: 0,
|
|
3
|
-
monday: 1,
|
|
4
|
-
tuesday: 2,
|
|
5
|
-
wednesday: 3,
|
|
6
|
-
thursday: 4,
|
|
7
|
-
friday: 5,
|
|
8
|
-
saturday: 6,
|
|
9
|
-
};
|
|
10
|
-
/**
|
|
11
|
-
* Calculates the next occurrence date based on recurrence type and optional weekdays
|
|
12
|
-
*/
|
|
13
|
-
export function getNextOccurrence(currentDate, recurrenceType, weekdays) {
|
|
14
|
-
switch (recurrenceType) {
|
|
15
|
-
case "daily":
|
|
16
|
-
return currentDate.plus({ days: 1 });
|
|
17
|
-
case "weekly":
|
|
18
|
-
if (weekdays && weekdays.length > 0) {
|
|
19
|
-
return getNextWeekdayOccurrence(currentDate, weekdays);
|
|
20
|
-
}
|
|
21
|
-
return currentDate.plus({ weeks: 1 });
|
|
22
|
-
case "bi-weekly":
|
|
23
|
-
if (weekdays && weekdays.length > 0) {
|
|
24
|
-
return getNextBiWeeklyOccurrence(currentDate, weekdays);
|
|
25
|
-
}
|
|
26
|
-
return currentDate.plus({ weeks: 2 });
|
|
27
|
-
case "monthly":
|
|
28
|
-
return currentDate.plus({ months: 1 });
|
|
29
|
-
case "bi-monthly":
|
|
30
|
-
return currentDate.plus({ months: 2 });
|
|
31
|
-
case "yearly":
|
|
32
|
-
return currentDate.plus({ years: 1 });
|
|
33
|
-
default:
|
|
34
|
-
return currentDate.plus({ days: 1 });
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Checks if a given date matches any of the specified weekdays
|
|
39
|
-
*/
|
|
40
|
-
export function isDateOnWeekdays(date, weekdays) {
|
|
41
|
-
const dateWeekday = date.weekday;
|
|
42
|
-
const luxonWeekdays = weekdays.map((day) => {
|
|
43
|
-
const dayNumber = WEEKDAY_TO_NUMBER[day];
|
|
44
|
-
return dayNumber === 0 ? 7 : dayNumber; // Convert Sunday from 0 to 7 for Luxon
|
|
45
|
-
});
|
|
46
|
-
return luxonWeekdays.includes(dateWeekday);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Finds the next occurrence on specified weekdays
|
|
50
|
-
*/
|
|
51
|
-
export function getNextWeekdayOccurrence(currentDate, weekdays) {
|
|
52
|
-
const currentWeekday = currentDate.weekday;
|
|
53
|
-
const luxonWeekdays = weekdays.map((day) => {
|
|
54
|
-
const dayNumber = WEEKDAY_TO_NUMBER[day];
|
|
55
|
-
return dayNumber === 0 ? 7 : dayNumber; // Convert Sunday from 0 to 7 for Luxon
|
|
56
|
-
});
|
|
57
|
-
// Find next weekday in the current week (after today)
|
|
58
|
-
const nextWeekday = luxonWeekdays.find((day) => day > currentWeekday);
|
|
59
|
-
if (nextWeekday) {
|
|
60
|
-
return currentDate.set({ weekday: nextWeekday });
|
|
61
|
-
}
|
|
62
|
-
// No more weekdays this week, go to first weekday of next week
|
|
63
|
-
const firstWeekday = Math.min(...luxonWeekdays);
|
|
64
|
-
return currentDate.plus({ weeks: 1 }).set({ weekday: firstWeekday });
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Finds the next bi-weekly occurrence on specified weekdays
|
|
68
|
-
*/
|
|
69
|
-
export function getNextBiWeeklyOccurrence(currentDate, weekdays) {
|
|
70
|
-
const nextWeekly = getNextWeekdayOccurrence(currentDate, weekdays);
|
|
71
|
-
// Add one more week to make it bi-weekly
|
|
72
|
-
return nextWeekly.plus({ weeks: 1 });
|
|
73
|
-
}
|
|
74
|
-
export function* iterateOccurrencesInRange(startDate, rrules, rangeStart, rangeEnd) {
|
|
75
|
-
// Normalize to start of day for comparison
|
|
76
|
-
const normalizedStart = startDate.startOf("day");
|
|
77
|
-
const normalizedRangeStart = rangeStart.startOf("day");
|
|
78
|
-
const normalizedRangeEnd = rangeEnd.startOf("day");
|
|
79
|
-
// Start from the later of startDate or rangeStart
|
|
80
|
-
let currentDate = normalizedStart >= normalizedRangeStart ? normalizedStart : normalizedRangeStart;
|
|
81
|
-
// For weekly/bi-weekly with weekdays, we need to track which week we're in
|
|
82
|
-
if ((rrules.type === "weekly" || rrules.type === "bi-weekly") &&
|
|
83
|
-
rrules.weekdays &&
|
|
84
|
-
rrules.weekdays.length > 0) {
|
|
85
|
-
// Calculate week offset from start date
|
|
86
|
-
const weeksFromStart = Math.floor(currentDate.diff(normalizedStart, "weeks").weeks);
|
|
87
|
-
// For bi-weekly, we only want even weeks (0, 2, 4...) from the start date
|
|
88
|
-
const weekInterval = rrules.type === "bi-weekly" ? 2 : 1;
|
|
89
|
-
// Adjust to the correct week if we're in an off-week
|
|
90
|
-
const weekOffset = weeksFromStart % weekInterval;
|
|
91
|
-
if (weekOffset !== 0) {
|
|
92
|
-
currentDate = currentDate.plus({ weeks: weekInterval - weekOffset });
|
|
93
|
-
}
|
|
94
|
-
// Now iterate through weeks, checking each day
|
|
95
|
-
while (currentDate <= normalizedRangeEnd) {
|
|
96
|
-
// Check all 7 days of the current week
|
|
97
|
-
for (let dayOffset = 0; dayOffset < 7; dayOffset++) {
|
|
98
|
-
const checkDate = currentDate.plus({ days: dayOffset });
|
|
99
|
-
// Only yield if within range and matches a target weekday
|
|
100
|
-
if (checkDate >= normalizedRangeStart &&
|
|
101
|
-
checkDate <= normalizedRangeEnd &&
|
|
102
|
-
isDateOnWeekdays(checkDate, rrules.weekdays)) {
|
|
103
|
-
yield checkDate;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
// Move to next occurrence week (1 week for weekly, 2 weeks for bi-weekly)
|
|
107
|
-
currentDate = currentDate.plus({ weeks: weekInterval });
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
// For other recurrence types (daily, monthly, yearly, or weekly without weekdays)
|
|
112
|
-
while (currentDate <= normalizedRangeEnd) {
|
|
113
|
-
if (currentDate >= normalizedRangeStart) {
|
|
114
|
-
yield currentDate;
|
|
115
|
-
}
|
|
116
|
-
const nextDate = getNextOccurrence(currentDate, rrules.type, rrules.weekdays);
|
|
117
|
-
if (nextDate <= normalizedRangeEnd) {
|
|
118
|
-
currentDate = nextDate;
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Calculates a DateTime for a specific date with optional time
|
|
128
|
-
*/
|
|
129
|
-
export function calculateInstanceDateTime(instanceDate, timeString) {
|
|
130
|
-
if (!timeString) {
|
|
131
|
-
return instanceDate.startOf("day");
|
|
132
|
-
}
|
|
133
|
-
const [hours, minutes] = timeString.split(":").map(Number);
|
|
134
|
-
return instanceDate.set({ hour: hours, minute: minutes, second: 0, millisecond: 0 });
|
|
135
|
-
}
|
|
136
|
-
export function calculateRecurringInstanceDateTime(nextInstanceDateTime, nodeRecuringEventDateTime, recurrenceType, allDay) {
|
|
137
|
-
// Convert the original event time to the target timezone once to preserve local time
|
|
138
|
-
const originalInTargetZone = nodeRecuringEventDateTime.setZone(nextInstanceDateTime.zone);
|
|
139
|
-
switch (recurrenceType) {
|
|
140
|
-
case "daily":
|
|
141
|
-
case "weekly":
|
|
142
|
-
case "bi-weekly": {
|
|
143
|
-
if (allDay) {
|
|
144
|
-
return nextInstanceDateTime.startOf("day");
|
|
145
|
-
}
|
|
146
|
-
return nextInstanceDateTime.set({
|
|
147
|
-
hour: originalInTargetZone.hour,
|
|
148
|
-
minute: originalInTargetZone.minute,
|
|
149
|
-
second: 0,
|
|
150
|
-
millisecond: 0,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
case "monthly":
|
|
154
|
-
case "bi-monthly": {
|
|
155
|
-
if (allDay) {
|
|
156
|
-
return nextInstanceDateTime.set({ day: originalInTargetZone.day }).startOf("day");
|
|
157
|
-
}
|
|
158
|
-
return nextInstanceDateTime.set({
|
|
159
|
-
day: originalInTargetZone.day,
|
|
160
|
-
hour: originalInTargetZone.hour,
|
|
161
|
-
minute: originalInTargetZone.minute,
|
|
162
|
-
second: 0,
|
|
163
|
-
millisecond: 0,
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
case "yearly": {
|
|
167
|
-
if (allDay) {
|
|
168
|
-
return nextInstanceDateTime
|
|
169
|
-
.set({
|
|
170
|
-
month: originalInTargetZone.month,
|
|
171
|
-
day: originalInTargetZone.day,
|
|
172
|
-
})
|
|
173
|
-
.startOf("day");
|
|
174
|
-
}
|
|
175
|
-
return nextInstanceDateTime.set({
|
|
176
|
-
month: originalInTargetZone.month,
|
|
177
|
-
day: originalInTargetZone.day,
|
|
178
|
-
hour: originalInTargetZone.hour,
|
|
179
|
-
minute: originalInTargetZone.minute,
|
|
180
|
-
second: 0,
|
|
181
|
-
millisecond: 0,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
default:
|
|
185
|
-
return nextInstanceDateTime.startOf("day");
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
//# sourceMappingURL=date-recurrence.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"date-recurrence.js","sourceRoot":"","sources":["../../src/date/date-recurrence.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DateTime } from \"luxon\";\n\nexport type RecurrenceType = \"daily\" | \"weekly\" | \"bi-weekly\" | \"monthly\" | \"bi-monthly\" | \"yearly\";\n\nexport type Weekday =\n\t| \"sunday\"\n\t| \"monday\"\n\t| \"tuesday\"\n\t| \"wednesday\"\n\t| \"thursday\"\n\t| \"friday\"\n\t| \"saturday\";\n\nexport const WEEKDAY_TO_NUMBER: Record<Weekday, number> = {\n\tsunday: 0,\n\tmonday: 1,\n\ttuesday: 2,\n\twednesday: 3,\n\tthursday: 4,\n\tfriday: 5,\n\tsaturday: 6,\n};\n\n/**\n * Calculates the next occurrence date based on recurrence type and optional weekdays\n */\nexport function getNextOccurrence(\n\tcurrentDate: DateTime,\n\trecurrenceType: RecurrenceType,\n\tweekdays?: Weekday[]\n): DateTime {\n\tswitch (recurrenceType) {\n\t\tcase \"daily\":\n\t\t\treturn currentDate.plus({ days: 1 });\n\t\tcase \"weekly\":\n\t\t\tif (weekdays && weekdays.length > 0) {\n\t\t\t\treturn getNextWeekdayOccurrence(currentDate, weekdays);\n\t\t\t}\n\t\t\treturn currentDate.plus({ weeks: 1 });\n\t\tcase \"bi-weekly\":\n\t\t\tif (weekdays && weekdays.length > 0) {\n\t\t\t\treturn getNextBiWeeklyOccurrence(currentDate, weekdays);\n\t\t\t}\n\t\t\treturn currentDate.plus({ weeks: 2 });\n\t\tcase \"monthly\":\n\t\t\treturn currentDate.plus({ months: 1 });\n\t\tcase \"bi-monthly\":\n\t\t\treturn currentDate.plus({ months: 2 });\n\t\tcase \"yearly\":\n\t\t\treturn currentDate.plus({ years: 1 });\n\t\tdefault:\n\t\t\treturn currentDate.plus({ days: 1 });\n\t}\n}\n\n/**\n * Checks if a given date matches any of the specified weekdays\n */\nexport function isDateOnWeekdays(date: DateTime, weekdays: Weekday[]): boolean {\n\tconst dateWeekday = date.weekday;\n\tconst luxonWeekdays = weekdays.map((day) => {\n\t\tconst dayNumber = WEEKDAY_TO_NUMBER[day];\n\t\treturn dayNumber === 0 ? 7 : dayNumber; // Convert Sunday from 0 to 7 for Luxon\n\t});\n\n\treturn luxonWeekdays.includes(dateWeekday);\n}\n\n/**\n * Finds the next occurrence on specified weekdays\n */\nexport function getNextWeekdayOccurrence(currentDate: DateTime, weekdays: Weekday[]): DateTime {\n\tconst currentWeekday = currentDate.weekday;\n\tconst luxonWeekdays = weekdays.map((day) => {\n\t\tconst dayNumber = WEEKDAY_TO_NUMBER[day];\n\t\treturn dayNumber === 0 ? 7 : dayNumber; // Convert Sunday from 0 to 7 for Luxon\n\t});\n\n\t// Find next weekday in the current week (after today)\n\tconst nextWeekday = luxonWeekdays.find((day) => day > currentWeekday);\n\tif (nextWeekday) {\n\t\treturn currentDate.set({ weekday: nextWeekday as 1 | 2 | 3 | 4 | 5 | 6 | 7 });\n\t}\n\n\t// No more weekdays this week, go to first weekday of next week\n\tconst firstWeekday = Math.min(...luxonWeekdays);\n\treturn currentDate.plus({ weeks: 1 }).set({ weekday: firstWeekday as 1 | 2 | 3 | 4 | 5 | 6 | 7 });\n}\n\n/**\n * Finds the next bi-weekly occurrence on specified weekdays\n */\nexport function getNextBiWeeklyOccurrence(currentDate: DateTime, weekdays: Weekday[]): DateTime {\n\tconst nextWeekly = getNextWeekdayOccurrence(currentDate, weekdays);\n\t// Add one more week to make it bi-weekly\n\treturn nextWeekly.plus({ weeks: 1 });\n}\n\nexport function* iterateOccurrencesInRange(\n\tstartDate: DateTime,\n\trrules: { type: RecurrenceType; weekdays?: Weekday[] },\n\trangeStart: DateTime,\n\trangeEnd: DateTime\n): Generator<DateTime, void, unknown> {\n\t// Normalize to start of day for comparison\n\tconst normalizedStart = startDate.startOf(\"day\");\n\tconst normalizedRangeStart = rangeStart.startOf(\"day\");\n\tconst normalizedRangeEnd = rangeEnd.startOf(\"day\");\n\n\t// Start from the later of startDate or rangeStart\n\tlet currentDate =\n\t\tnormalizedStart >= normalizedRangeStart ? normalizedStart : normalizedRangeStart;\n\n\t// For weekly/bi-weekly with weekdays, we need to track which week we're in\n\tif (\n\t\t(rrules.type === \"weekly\" || rrules.type === \"bi-weekly\") &&\n\t\trrules.weekdays &&\n\t\trrules.weekdays.length > 0\n\t) {\n\t\t// Calculate week offset from start date\n\t\tconst weeksFromStart = Math.floor(currentDate.diff(normalizedStart, \"weeks\").weeks);\n\n\t\t// For bi-weekly, we only want even weeks (0, 2, 4...) from the start date\n\t\tconst weekInterval = rrules.type === \"bi-weekly\" ? 2 : 1;\n\n\t\t// Adjust to the correct week if we're in an off-week\n\t\tconst weekOffset = weeksFromStart % weekInterval;\n\t\tif (weekOffset !== 0) {\n\t\t\tcurrentDate = currentDate.plus({ weeks: weekInterval - weekOffset });\n\t\t}\n\n\t\t// Now iterate through weeks, checking each day\n\t\twhile (currentDate <= normalizedRangeEnd) {\n\t\t\t// Check all 7 days of the current week\n\t\t\tfor (let dayOffset = 0; dayOffset < 7; dayOffset++) {\n\t\t\t\tconst checkDate = currentDate.plus({ days: dayOffset });\n\n\t\t\t\t// Only yield if within range and matches a target weekday\n\t\t\t\tif (\n\t\t\t\t\tcheckDate >= normalizedRangeStart &&\n\t\t\t\t\tcheckDate <= normalizedRangeEnd &&\n\t\t\t\t\tisDateOnWeekdays(checkDate, rrules.weekdays)\n\t\t\t\t) {\n\t\t\t\t\tyield checkDate;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Move to next occurrence week (1 week for weekly, 2 weeks for bi-weekly)\n\t\t\tcurrentDate = currentDate.plus({ weeks: weekInterval });\n\t\t}\n\t} else {\n\t\t// For other recurrence types (daily, monthly, yearly, or weekly without weekdays)\n\t\twhile (currentDate <= normalizedRangeEnd) {\n\t\t\tif (currentDate >= normalizedRangeStart) {\n\t\t\t\tyield currentDate;\n\t\t\t}\n\n\t\t\tconst nextDate = getNextOccurrence(currentDate, rrules.type, rrules.weekdays);\n\n\t\t\tif (nextDate <= normalizedRangeEnd) {\n\t\t\t\tcurrentDate = nextDate;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Calculates a DateTime for a specific date with optional time\n */\nexport function calculateInstanceDateTime(instanceDate: DateTime, timeString?: string): DateTime {\n\tif (!timeString) {\n\t\treturn instanceDate.startOf(\"day\");\n\t}\n\n\tconst [hours, minutes] = timeString.split(\":\").map(Number);\n\treturn instanceDate.set({ hour: hours, minute: minutes, second: 0, millisecond: 0 });\n}\n\nexport function calculateRecurringInstanceDateTime(\n\tnextInstanceDateTime: DateTime,\n\tnodeRecuringEventDateTime: DateTime,\n\trecurrenceType: RecurrenceType,\n\tallDay?: boolean\n): DateTime {\n\t// Convert the original event time to the target timezone once to preserve local time\n\tconst originalInTargetZone = nodeRecuringEventDateTime.setZone(nextInstanceDateTime.zone);\n\n\tswitch (recurrenceType) {\n\t\tcase \"daily\":\n\t\tcase \"weekly\":\n\t\tcase \"bi-weekly\": {\n\t\t\tif (allDay) {\n\t\t\t\treturn nextInstanceDateTime.startOf(\"day\");\n\t\t\t}\n\n\t\t\treturn nextInstanceDateTime.set({\n\t\t\t\thour: originalInTargetZone.hour,\n\t\t\t\tminute: originalInTargetZone.minute,\n\t\t\t\tsecond: 0,\n\t\t\t\tmillisecond: 0,\n\t\t\t});\n\t\t}\n\n\t\tcase \"monthly\":\n\t\tcase \"bi-monthly\": {\n\t\t\tif (allDay) {\n\t\t\t\treturn nextInstanceDateTime.set({ day: originalInTargetZone.day }).startOf(\"day\");\n\t\t\t}\n\n\t\t\treturn nextInstanceDateTime.set({\n\t\t\t\tday: originalInTargetZone.day,\n\t\t\t\thour: originalInTargetZone.hour,\n\t\t\t\tminute: originalInTargetZone.minute,\n\t\t\t\tsecond: 0,\n\t\t\t\tmillisecond: 0,\n\t\t\t});\n\t\t}\n\n\t\tcase \"yearly\": {\n\t\t\tif (allDay) {\n\t\t\t\treturn nextInstanceDateTime\n\t\t\t\t\t.set({\n\t\t\t\t\t\tmonth: originalInTargetZone.month,\n\t\t\t\t\t\tday: originalInTargetZone.day,\n\t\t\t\t\t})\n\t\t\t\t\t.startOf(\"day\");\n\t\t\t}\n\n\t\t\treturn nextInstanceDateTime.set({\n\t\t\t\tmonth: originalInTargetZone.month,\n\t\t\t\tday: originalInTargetZone.day,\n\t\t\t\thour: originalInTargetZone.hour,\n\t\t\t\tminute: originalInTargetZone.minute,\n\t\t\t\tsecond: 0,\n\t\t\t\tmillisecond: 0,\n\t\t\t});\n\t\t}\n\n\t\tdefault:\n\t\t\treturn nextInstanceDateTime.startOf(\"day\");\n\t}\n}\n"]}
|
package/dist/date/date.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { DateTime } from "luxon";
|
|
2
|
-
export declare const formatDateTimeForInput: (dateString: string) => string;
|
|
3
|
-
export declare const formatDateForInput: (dateString: string) => string;
|
|
4
|
-
/**
|
|
5
|
-
* Converts input value to ISO string, handling edge cases where
|
|
6
|
-
* browser datetime-local inputs behave differently across platforms.
|
|
7
|
-
* Returns null for invalid dates to prevent silent failures.
|
|
8
|
-
*/
|
|
9
|
-
export declare const inputValueToISOString: (inputValue: string) => string | null;
|
|
10
|
-
export declare const formatDuration: (minutes: number) => string;
|
|
11
|
-
/**
|
|
12
|
-
* Parse time string from datetime value - returns DateTime object
|
|
13
|
-
* Rejects plain HH:mm format, requires full datetime
|
|
14
|
-
*/
|
|
15
|
-
export declare const parseTimeString: (value: string | null) => DateTime | undefined;
|
|
16
|
-
/**
|
|
17
|
-
* Parse and validate datetime strings for event parsing
|
|
18
|
-
* Supports multiple formats including date-only and datetime formats
|
|
19
|
-
*/
|
|
20
|
-
export declare const parseDateTimeString: (value: string | null) => DateTime | undefined;
|
|
21
|
-
//# sourceMappingURL=date.d.ts.map
|
package/dist/date/date.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/date/date.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,eAAO,MAAM,sBAAsB,GAAI,YAAY,MAAM,KAAG,MAgB3D,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,YAAY,MAAM,KAAG,MAavD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,YAAY,MAAM,KAAG,MAAM,GAAG,IAMnE,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,MAIhD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,GAAG,IAAI,KAAG,QAAQ,GAAG,SAgBjE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,GAAG,IAAI,KAAG,QAAQ,GAAG,SA8BrE,CAAC"}
|