@real1ty-obsidian-plugins/utils 2.12.0 → 2.15.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 (50) hide show
  1. package/dist/components/frontmatter-propagation-modal.d.ts +16 -0
  2. package/dist/components/frontmatter-propagation-modal.d.ts.map +1 -0
  3. package/dist/components/frontmatter-propagation-modal.js +81 -0
  4. package/dist/components/frontmatter-propagation-modal.js.map +1 -0
  5. package/dist/components/index.d.ts +3 -0
  6. package/dist/components/index.d.ts.map +1 -0
  7. package/dist/components/index.js +3 -0
  8. package/dist/components/index.js.map +1 -0
  9. package/dist/components/input-managers/base.d.ts +30 -0
  10. package/dist/components/input-managers/base.d.ts.map +1 -0
  11. package/dist/components/input-managers/base.js +115 -0
  12. package/dist/components/input-managers/base.js.map +1 -0
  13. package/dist/components/input-managers/expression.d.ts +12 -0
  14. package/dist/components/input-managers/expression.d.ts.map +1 -0
  15. package/dist/components/input-managers/expression.js +56 -0
  16. package/dist/components/input-managers/expression.js.map +1 -0
  17. package/dist/components/input-managers/index.d.ts +4 -0
  18. package/dist/components/input-managers/index.d.ts.map +1 -0
  19. package/dist/components/input-managers/index.js +4 -0
  20. package/dist/components/input-managers/index.js.map +1 -0
  21. package/dist/components/input-managers/search.d.ts +6 -0
  22. package/dist/components/input-managers/search.d.ts.map +1 -0
  23. package/dist/components/input-managers/search.js +16 -0
  24. package/dist/components/input-managers/search.js.map +1 -0
  25. package/dist/core/evaluator/base.d.ts.map +1 -1
  26. package/dist/core/evaluator/base.js +12 -3
  27. package/dist/core/evaluator/base.js.map +1 -1
  28. package/dist/file/frontmatter-diff.d.ts +38 -0
  29. package/dist/file/frontmatter-diff.d.ts.map +1 -0
  30. package/dist/file/frontmatter-diff.js +162 -0
  31. package/dist/file/frontmatter-diff.js.map +1 -0
  32. package/dist/file/index.d.ts +1 -0
  33. package/dist/file/index.d.ts.map +1 -1
  34. package/dist/file/index.js +1 -0
  35. package/dist/file/index.js.map +1 -1
  36. package/dist/index.d.ts +1 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +2 -0
  39. package/dist/index.js.map +1 -1
  40. package/package.json +1 -1
  41. package/src/components/frontmatter-propagation-modal.ts +111 -0
  42. package/src/components/index.ts +2 -0
  43. package/src/components/input-managers/base.ts +150 -0
  44. package/src/components/input-managers/expression.ts +92 -0
  45. package/src/components/input-managers/index.ts +3 -0
  46. package/src/components/input-managers/search.ts +25 -0
  47. package/src/core/evaluator/base.ts +15 -3
  48. package/src/file/frontmatter-diff.ts +198 -0
  49. package/src/file/index.ts +1 -0
  50. package/src/index.ts +2 -0
@@ -0,0 +1,16 @@
1
+ import { type App, Modal } from "obsidian";
2
+ import type { FrontmatterDiff } from "../file/frontmatter-diff";
3
+ export interface FrontmatterPropagationModalOptions {
4
+ eventTitle: string;
5
+ diff: FrontmatterDiff;
6
+ instanceCount: number;
7
+ onConfirm: () => void | Promise<void>;
8
+ onCancel?: () => void | Promise<void>;
9
+ }
10
+ export declare class FrontmatterPropagationModal extends Modal {
11
+ private options;
12
+ constructor(app: App, options: FrontmatterPropagationModalOptions);
13
+ onOpen(): void;
14
+ onClose(): void;
15
+ }
16
+ //# sourceMappingURL=frontmatter-propagation-modal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter-propagation-modal.d.ts","sourceRoot":"","sources":["../../src/components/frontmatter-propagation-modal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGhE,MAAM,WAAW,kCAAkC;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,eAAe,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACrD,OAAO,CAAC,OAAO,CAAqC;gBAExC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,kCAAkC;IAKjE,MAAM,IAAI,IAAI;IAqFd,OAAO,IAAI,IAAI;CAIf"}
@@ -0,0 +1,81 @@
1
+ import { Modal } from "obsidian";
2
+ import { formatChangeForDisplay } from "../file/frontmatter-diff";
3
+ export class FrontmatterPropagationModal extends Modal {
4
+ constructor(app, options) {
5
+ super(app);
6
+ this.options = options;
7
+ }
8
+ onOpen() {
9
+ const { contentEl } = this;
10
+ contentEl.empty();
11
+ contentEl.createEl("h2", { text: "Propagate frontmatter changes?" });
12
+ contentEl.createEl("p", {
13
+ text: `The recurring event "${this.options.eventTitle}" has frontmatter changes. Do you want to apply these changes to all ${this.options.instanceCount} physical instances?`,
14
+ });
15
+ const changesContainer = contentEl.createDiv({ cls: "prisma-frontmatter-changes" });
16
+ if (this.options.diff.added.length > 0) {
17
+ const addedSection = changesContainer.createDiv({ cls: "prisma-changes-section" });
18
+ addedSection.createEl("h4", { text: "Added properties:" });
19
+ const addedList = addedSection.createEl("ul");
20
+ for (const change of this.options.diff.added) {
21
+ addedList.createEl("li", {
22
+ text: formatChangeForDisplay(change),
23
+ cls: "prisma-change-added",
24
+ });
25
+ }
26
+ }
27
+ if (this.options.diff.modified.length > 0) {
28
+ const modifiedSection = changesContainer.createDiv({ cls: "prisma-changes-section" });
29
+ modifiedSection.createEl("h4", { text: "Modified properties:" });
30
+ const modifiedList = modifiedSection.createEl("ul");
31
+ for (const change of this.options.diff.modified) {
32
+ modifiedList.createEl("li", {
33
+ text: formatChangeForDisplay(change),
34
+ cls: "prisma-change-modified",
35
+ });
36
+ }
37
+ }
38
+ if (this.options.diff.deleted.length > 0) {
39
+ const deletedSection = changesContainer.createDiv({ cls: "prisma-changes-section" });
40
+ deletedSection.createEl("h4", { text: "Deleted properties:" });
41
+ const deletedList = deletedSection.createEl("ul");
42
+ for (const change of this.options.diff.deleted) {
43
+ deletedList.createEl("li", {
44
+ text: formatChangeForDisplay(change),
45
+ cls: "prisma-change-deleted",
46
+ });
47
+ }
48
+ }
49
+ const buttonContainer = contentEl.createDiv({ cls: "prisma-modal-buttons" });
50
+ const yesButton = buttonContainer.createEl("button", {
51
+ text: "Yes, propagate",
52
+ cls: "mod-cta",
53
+ });
54
+ yesButton.addEventListener("click", () => {
55
+ void Promise.resolve(this.options.onConfirm())
56
+ .then(() => {
57
+ this.close();
58
+ })
59
+ .catch((error) => {
60
+ console.error("Error in onConfirm callback:", error);
61
+ this.close();
62
+ });
63
+ });
64
+ const noButton = buttonContainer.createEl("button", { text: "No, skip" });
65
+ noButton.addEventListener("click", () => {
66
+ var _a, _b;
67
+ const result = (_b = (_a = this.options).onCancel) === null || _b === void 0 ? void 0 : _b.call(_a);
68
+ if (result instanceof Promise) {
69
+ void result.catch((error) => {
70
+ console.error("Error in onCancel callback:", error);
71
+ });
72
+ }
73
+ this.close();
74
+ });
75
+ }
76
+ onClose() {
77
+ const { contentEl } = this;
78
+ contentEl.empty();
79
+ }
80
+ }
81
+ //# sourceMappingURL=frontmatter-propagation-modal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter-propagation-modal.js","sourceRoot":"","sources":["../../src/components/frontmatter-propagation-modal.ts"],"names":[],"mappings":"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","sourcesContent":["import { type App, Modal } from \"obsidian\";\n\nimport type { FrontmatterDiff } from \"../file/frontmatter-diff\";\nimport { formatChangeForDisplay } from \"../file/frontmatter-diff\";\n\nexport interface FrontmatterPropagationModalOptions {\n\teventTitle: string;\n\tdiff: FrontmatterDiff;\n\tinstanceCount: number;\n\tonConfirm: () => void | Promise<void>;\n\tonCancel?: () => void | Promise<void>;\n}\n\nexport class FrontmatterPropagationModal extends Modal {\n\tprivate options: FrontmatterPropagationModalOptions;\n\n\tconstructor(app: App, options: FrontmatterPropagationModalOptions) {\n\t\tsuper(app);\n\t\tthis.options = options;\n\t}\n\n\tonOpen(): void {\n\t\tconst { contentEl } = this;\n\n\t\tcontentEl.empty();\n\n\t\tcontentEl.createEl(\"h2\", { text: \"Propagate frontmatter changes?\" });\n\n\t\tcontentEl.createEl(\"p\", {\n\t\t\ttext: `The recurring event \"${this.options.eventTitle}\" has frontmatter changes. Do you want to apply these changes to all ${this.options.instanceCount} physical instances?`,\n\t\t});\n\n\t\tconst changesContainer = contentEl.createDiv({ cls: \"prisma-frontmatter-changes\" });\n\n\t\tif (this.options.diff.added.length > 0) {\n\t\t\tconst addedSection = changesContainer.createDiv({ cls: \"prisma-changes-section\" });\n\t\t\taddedSection.createEl(\"h4\", { text: \"Added properties:\" });\n\t\t\tconst addedList = addedSection.createEl(\"ul\");\n\n\t\t\tfor (const change of this.options.diff.added) {\n\t\t\t\taddedList.createEl(\"li\", {\n\t\t\t\t\ttext: formatChangeForDisplay(change),\n\t\t\t\t\tcls: \"prisma-change-added\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (this.options.diff.modified.length > 0) {\n\t\t\tconst modifiedSection = changesContainer.createDiv({ cls: \"prisma-changes-section\" });\n\t\t\tmodifiedSection.createEl(\"h4\", { text: \"Modified properties:\" });\n\t\t\tconst modifiedList = modifiedSection.createEl(\"ul\");\n\n\t\t\tfor (const change of this.options.diff.modified) {\n\t\t\t\tmodifiedList.createEl(\"li\", {\n\t\t\t\t\ttext: formatChangeForDisplay(change),\n\t\t\t\t\tcls: \"prisma-change-modified\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (this.options.diff.deleted.length > 0) {\n\t\t\tconst deletedSection = changesContainer.createDiv({ cls: \"prisma-changes-section\" });\n\t\t\tdeletedSection.createEl(\"h4\", { text: \"Deleted properties:\" });\n\t\t\tconst deletedList = deletedSection.createEl(\"ul\");\n\n\t\t\tfor (const change of this.options.diff.deleted) {\n\t\t\t\tdeletedList.createEl(\"li\", {\n\t\t\t\t\ttext: formatChangeForDisplay(change),\n\t\t\t\t\tcls: \"prisma-change-deleted\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst buttonContainer = contentEl.createDiv({ cls: \"prisma-modal-buttons\" });\n\n\t\tconst yesButton = buttonContainer.createEl(\"button\", {\n\t\t\ttext: \"Yes, propagate\",\n\t\t\tcls: \"mod-cta\",\n\t\t});\n\n\t\tyesButton.addEventListener(\"click\", () => {\n\t\t\tvoid Promise.resolve(this.options.onConfirm())\n\t\t\t\t.then(() => {\n\t\t\t\t\tthis.close();\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tconsole.error(\"Error in onConfirm callback:\", error);\n\t\t\t\t\tthis.close();\n\t\t\t\t});\n\t\t});\n\n\t\tconst noButton = buttonContainer.createEl(\"button\", { text: \"No, skip\" });\n\n\t\tnoButton.addEventListener(\"click\", () => {\n\t\t\tconst result = this.options.onCancel?.();\n\n\t\t\tif (result instanceof Promise) {\n\t\t\t\tvoid result.catch((error) => {\n\t\t\t\t\tconsole.error(\"Error in onCancel callback:\", error);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.close();\n\t\t});\n\t}\n\n\tonClose(): void {\n\t\tconst { contentEl } = this;\n\t\tcontentEl.empty();\n\t}\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export * from "./frontmatter-propagation-modal";
2
+ export * from "./input-managers";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from "./frontmatter-propagation-modal";
2
+ export * from "./input-managers";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,kBAAkB,CAAC","sourcesContent":["export * from \"./frontmatter-propagation-modal\";\nexport * from \"./input-managers\";\n"]}
@@ -0,0 +1,30 @@
1
+ export type InputManagerFilterChangeCallback = () => void;
2
+ export declare abstract class InputManager {
3
+ protected parentEl: HTMLElement;
4
+ protected placeholder: string;
5
+ protected cssPrefix: string;
6
+ protected onFilterChange: InputManagerFilterChangeCallback;
7
+ protected containerEl: HTMLElement;
8
+ protected inputEl: HTMLInputElement | null;
9
+ protected debounceTimer: number | null;
10
+ protected currentValue: string;
11
+ protected persistentlyVisible: boolean;
12
+ protected onHide?: () => void;
13
+ protected hiddenClass: string;
14
+ protected debounceMs: number;
15
+ protected cssClass: string;
16
+ constructor(parentEl: HTMLElement, placeholder: string, cssPrefix: string, onFilterChange: InputManagerFilterChangeCallback, initiallyVisible: boolean, onHide?: () => void, debounceMs?: number);
17
+ private render;
18
+ private handleInputChange;
19
+ protected applyFilterImmediately(): void;
20
+ protected updateFilterValue(value: string): void;
21
+ getCurrentValue(): string;
22
+ show(): void;
23
+ hide(): void;
24
+ focus(): void;
25
+ isVisible(): boolean;
26
+ setPersistentlyVisible(value: boolean): void;
27
+ destroy(): void;
28
+ abstract shouldInclude(data: unknown): boolean;
29
+ }
30
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/components/input-managers/base.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gCAAgC,GAAG,MAAM,IAAI,CAAC;AAI1D,8BAAsB,YAAY;IAYhC,SAAS,CAAC,QAAQ,EAAE,WAAW;IAC/B,SAAS,CAAC,WAAW,EAAE,MAAM;IAC7B,SAAS,CAAC,SAAS,EAAE,MAAM;IAC3B,SAAS,CAAC,cAAc,EAAE,gCAAgC;IAd3D,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IACnC,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IAClD,SAAS,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC9C,SAAS,CAAC,YAAY,SAAM;IAC5B,SAAS,CAAC,mBAAmB,UAAS;IACtC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAGhB,QAAQ,EAAE,WAAW,EACrB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,gCAAgC,EAC1D,gBAAgB,EAAE,OAAO,EACzB,MAAM,CAAC,EAAE,MAAM,IAAI,EACnB,UAAU,GAAE,MAA4B;IAmBzC,OAAO,CAAC,MAAM;IA0Bd,OAAO,CAAC,iBAAiB;IAUzB,SAAS,CAAC,sBAAsB,IAAI,IAAI;IAQxC,SAAS,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAMhD,eAAe,IAAI,MAAM;IAIzB,IAAI,IAAI,IAAI;IAMZ,IAAI,IAAI,IAAI;IAiBZ,KAAK,IAAI,IAAI;IAIb,SAAS,IAAI,OAAO;IAIpB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAU5C,OAAO,IAAI,IAAI;IAYf,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO;CAC9C"}
@@ -0,0 +1,115 @@
1
+ const DEFAULT_DEBOUNCE_MS = 150;
2
+ export class InputManager {
3
+ constructor(parentEl, placeholder, cssPrefix, onFilterChange, initiallyVisible, onHide, debounceMs = DEFAULT_DEBOUNCE_MS) {
4
+ this.parentEl = parentEl;
5
+ this.placeholder = placeholder;
6
+ this.cssPrefix = cssPrefix;
7
+ this.onFilterChange = onFilterChange;
8
+ this.inputEl = null;
9
+ this.debounceTimer = null;
10
+ this.currentValue = "";
11
+ this.persistentlyVisible = false;
12
+ this.hiddenClass = `${cssPrefix}-hidden`;
13
+ this.debounceMs = debounceMs;
14
+ this.cssClass = `${cssPrefix}-input`;
15
+ const classes = initiallyVisible
16
+ ? `${cssPrefix}-container`
17
+ : `${cssPrefix}-container ${this.hiddenClass}`;
18
+ this.containerEl = this.parentEl.createEl("div", {
19
+ cls: classes,
20
+ });
21
+ this.onHide = onHide;
22
+ this.render();
23
+ }
24
+ render() {
25
+ this.inputEl = this.containerEl.createEl("input", {
26
+ type: "text",
27
+ cls: this.cssClass,
28
+ placeholder: this.placeholder,
29
+ });
30
+ this.inputEl.addEventListener("input", () => {
31
+ this.handleInputChange();
32
+ });
33
+ this.inputEl.addEventListener("keydown", (evt) => {
34
+ var _a;
35
+ if (evt.key === "Escape") {
36
+ // Only allow hiding if not persistently visible
37
+ if (!this.persistentlyVisible) {
38
+ this.hide();
39
+ }
40
+ else {
41
+ // Just blur the input if persistently visible
42
+ (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.blur();
43
+ }
44
+ }
45
+ else if (evt.key === "Enter") {
46
+ this.applyFilterImmediately();
47
+ }
48
+ });
49
+ }
50
+ handleInputChange() {
51
+ if (this.debounceTimer !== null) {
52
+ window.clearTimeout(this.debounceTimer);
53
+ }
54
+ this.debounceTimer = window.setTimeout(() => {
55
+ this.applyFilterImmediately();
56
+ }, this.debounceMs);
57
+ }
58
+ applyFilterImmediately() {
59
+ var _a, _b;
60
+ const newValue = (_b = (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.value.trim()) !== null && _b !== void 0 ? _b : "";
61
+ if (newValue !== this.currentValue) {
62
+ this.updateFilterValue(newValue);
63
+ }
64
+ }
65
+ updateFilterValue(value) {
66
+ this.currentValue = value;
67
+ this.onFilterChange();
68
+ }
69
+ getCurrentValue() {
70
+ return this.currentValue;
71
+ }
72
+ show() {
73
+ var _a;
74
+ this.containerEl.removeClass(this.hiddenClass);
75
+ (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.focus();
76
+ }
77
+ hide() {
78
+ var _a;
79
+ // Don't allow hiding if persistently visible
80
+ if (this.persistentlyVisible) {
81
+ return;
82
+ }
83
+ this.containerEl.addClass(this.hiddenClass);
84
+ if (this.inputEl) {
85
+ this.inputEl.value = "";
86
+ }
87
+ this.updateFilterValue("");
88
+ (_a = this.onHide) === null || _a === void 0 ? void 0 : _a.call(this);
89
+ }
90
+ focus() {
91
+ var _a;
92
+ (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.focus();
93
+ }
94
+ isVisible() {
95
+ return !this.containerEl.hasClass(this.hiddenClass);
96
+ }
97
+ setPersistentlyVisible(value) {
98
+ this.persistentlyVisible = value;
99
+ if (value) {
100
+ this.show();
101
+ }
102
+ else {
103
+ this.hide();
104
+ }
105
+ }
106
+ destroy() {
107
+ if (this.debounceTimer !== null) {
108
+ window.clearTimeout(this.debounceTimer);
109
+ this.debounceTimer = null;
110
+ }
111
+ this.containerEl.remove();
112
+ this.inputEl = null;
113
+ }
114
+ }
115
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/components/input-managers/base.ts"],"names":[],"mappings":"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","sourcesContent":["export type InputManagerFilterChangeCallback = () => void;\n\nconst DEFAULT_DEBOUNCE_MS = 150;\n\nexport abstract class InputManager {\n\tprotected containerEl: HTMLElement;\n\tprotected inputEl: HTMLInputElement | null = null;\n\tprotected debounceTimer: number | null = null;\n\tprotected currentValue = \"\";\n\tprotected persistentlyVisible = false;\n\tprotected onHide?: () => void;\n\tprotected hiddenClass: string;\n\tprotected debounceMs: number;\n\tprotected cssClass: string;\n\n\tconstructor(\n\t\tprotected parentEl: HTMLElement,\n\t\tprotected placeholder: string,\n\t\tprotected cssPrefix: string,\n\t\tprotected onFilterChange: InputManagerFilterChangeCallback,\n\t\tinitiallyVisible: boolean,\n\t\tonHide?: () => void,\n\t\tdebounceMs: number = DEFAULT_DEBOUNCE_MS\n\t) {\n\t\tthis.hiddenClass = `${cssPrefix}-hidden`;\n\t\tthis.debounceMs = debounceMs;\n\t\tthis.cssClass = `${cssPrefix}-input`;\n\n\t\tconst classes = initiallyVisible\n\t\t\t? `${cssPrefix}-container`\n\t\t\t: `${cssPrefix}-container ${this.hiddenClass}`;\n\n\t\tthis.containerEl = this.parentEl.createEl(\"div\", {\n\t\t\tcls: classes,\n\t\t});\n\n\t\tthis.onHide = onHide;\n\n\t\tthis.render();\n\t}\n\n\tprivate render(): void {\n\t\tthis.inputEl = this.containerEl.createEl(\"input\", {\n\t\t\ttype: \"text\",\n\t\t\tcls: this.cssClass,\n\t\t\tplaceholder: this.placeholder,\n\t\t});\n\n\t\tthis.inputEl.addEventListener(\"input\", () => {\n\t\t\tthis.handleInputChange();\n\t\t});\n\n\t\tthis.inputEl.addEventListener(\"keydown\", (evt) => {\n\t\t\tif (evt.key === \"Escape\") {\n\t\t\t\t// Only allow hiding if not persistently visible\n\t\t\t\tif (!this.persistentlyVisible) {\n\t\t\t\t\tthis.hide();\n\t\t\t\t} else {\n\t\t\t\t\t// Just blur the input if persistently visible\n\t\t\t\t\tthis.inputEl?.blur();\n\t\t\t\t}\n\t\t\t} else if (evt.key === \"Enter\") {\n\t\t\t\tthis.applyFilterImmediately();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate handleInputChange(): void {\n\t\tif (this.debounceTimer !== null) {\n\t\t\twindow.clearTimeout(this.debounceTimer);\n\t\t}\n\n\t\tthis.debounceTimer = window.setTimeout(() => {\n\t\t\tthis.applyFilterImmediately();\n\t\t}, this.debounceMs);\n\t}\n\n\tprotected applyFilterImmediately(): void {\n\t\tconst newValue = this.inputEl?.value.trim() ?? \"\";\n\n\t\tif (newValue !== this.currentValue) {\n\t\t\tthis.updateFilterValue(newValue);\n\t\t}\n\t}\n\n\tprotected updateFilterValue(value: string): void {\n\t\tthis.currentValue = value;\n\n\t\tthis.onFilterChange();\n\t}\n\n\tgetCurrentValue(): string {\n\t\treturn this.currentValue;\n\t}\n\n\tshow(): void {\n\t\tthis.containerEl.removeClass(this.hiddenClass);\n\n\t\tthis.inputEl?.focus();\n\t}\n\n\thide(): void {\n\t\t// Don't allow hiding if persistently visible\n\t\tif (this.persistentlyVisible) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.containerEl.addClass(this.hiddenClass);\n\n\t\tif (this.inputEl) {\n\t\t\tthis.inputEl.value = \"\";\n\t\t}\n\n\t\tthis.updateFilterValue(\"\");\n\n\t\tthis.onHide?.();\n\t}\n\n\tfocus(): void {\n\t\tthis.inputEl?.focus();\n\t}\n\n\tisVisible(): boolean {\n\t\treturn !this.containerEl.hasClass(this.hiddenClass);\n\t}\n\n\tsetPersistentlyVisible(value: boolean): void {\n\t\tthis.persistentlyVisible = value;\n\n\t\tif (value) {\n\t\t\tthis.show();\n\t\t} else {\n\t\t\tthis.hide();\n\t\t}\n\t}\n\n\tdestroy(): void {\n\t\tif (this.debounceTimer !== null) {\n\t\t\twindow.clearTimeout(this.debounceTimer);\n\n\t\t\tthis.debounceTimer = null;\n\t\t}\n\n\t\tthis.containerEl.remove();\n\n\t\tthis.inputEl = null;\n\t}\n\n\tabstract shouldInclude(data: unknown): boolean;\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { InputManager } from "./base";
2
+ export declare class ExpressionFilterInputManager extends InputManager {
3
+ private compiledFunc;
4
+ private propertyMapping;
5
+ private lastWarnedExpression;
6
+ constructor(parentEl: HTMLElement, cssPrefix: string, onFilterChange: () => void, initiallyVisible?: boolean, placeholder?: string, onHide?: () => void, debounceMs?: number);
7
+ protected updateFilterValue(filterValue: string): void;
8
+ shouldInclude(event: {
9
+ meta?: Record<string, unknown>;
10
+ }): boolean;
11
+ }
12
+ //# sourceMappingURL=expression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../../src/components/input-managers/expression.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,qBAAa,4BAA6B,SAAQ,YAAY;IAC7D,OAAO,CAAC,YAAY,CAAkD;IAEtE,OAAO,CAAC,eAAe,CAA6B;IAEpD,OAAO,CAAC,oBAAoB,CAAuB;gBAGlD,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,IAAI,EAC1B,gBAAgB,GAAE,OAAe,EACjC,WAAW,GAAE,MAA4B,EACzC,MAAM,CAAC,EAAE,MAAM,IAAI,EACnB,UAAU,CAAC,EAAE,MAAM;IASpB,SAAS,CAAC,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAUtD,aAAa,CAAC,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO;CAsDjE"}
@@ -0,0 +1,56 @@
1
+ import { buildPropertyMapping, sanitizeExpression } from "../../core/expression-utils";
2
+ import { InputManager } from "./base";
3
+ export class ExpressionFilterInputManager extends InputManager {
4
+ constructor(parentEl, cssPrefix, onFilterChange, initiallyVisible = false, placeholder = "Status === 'Done'", onHide, debounceMs) {
5
+ super(parentEl, placeholder, cssPrefix, onFilterChange, initiallyVisible, onHide, debounceMs);
6
+ this.compiledFunc = null;
7
+ this.propertyMapping = new Map();
8
+ this.lastWarnedExpression = null;
9
+ this.cssClass = `${cssPrefix}-expression-input`;
10
+ if (this.inputEl) {
11
+ this.inputEl.className = this.cssClass;
12
+ }
13
+ }
14
+ updateFilterValue(filterValue) {
15
+ super.updateFilterValue(filterValue);
16
+ this.compiledFunc = null;
17
+ this.propertyMapping.clear();
18
+ this.lastWarnedExpression = null;
19
+ }
20
+ shouldInclude(event) {
21
+ if (!this.currentValue)
22
+ return true;
23
+ const frontmatter = event.meta || {};
24
+ try {
25
+ const currentKeys = new Set(Object.keys(frontmatter));
26
+ const existingKeys = new Set(this.propertyMapping.keys());
27
+ const newKeys = [...currentKeys].filter((key) => !existingKeys.has(key));
28
+ if (newKeys.length > 0) {
29
+ const allKeys = new Set([...existingKeys, ...currentKeys]);
30
+ this.propertyMapping = buildPropertyMapping(Array.from(allKeys));
31
+ this.compiledFunc = null;
32
+ }
33
+ if (!this.compiledFunc) {
34
+ const sanitized = sanitizeExpression(this.currentValue, this.propertyMapping);
35
+ const params = Array.from(this.propertyMapping.values());
36
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval -- Dynamic function creation for expression evaluation with sanitized input
37
+ this.compiledFunc = new Function(...params, `"use strict"; return ${sanitized};`);
38
+ }
39
+ const values = Array.from(this.propertyMapping.keys()).map((key) => { var _a; return (_a = frontmatter[key]) !== null && _a !== void 0 ? _a : undefined; });
40
+ const result = this.compiledFunc(...values);
41
+ return result;
42
+ }
43
+ catch (error) {
44
+ if (error instanceof ReferenceError) {
45
+ const hasInequality = this.currentValue.includes("!==") || this.currentValue.includes("!=");
46
+ return hasInequality;
47
+ }
48
+ if (this.lastWarnedExpression !== this.currentValue) {
49
+ console.warn("Invalid filter expression:", this.currentValue, error);
50
+ this.lastWarnedExpression = this.currentValue;
51
+ }
52
+ return false;
53
+ }
54
+ }
55
+ }
56
+ //# sourceMappingURL=expression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression.js","sourceRoot":"","sources":["../../../src/components/input-managers/expression.ts"],"names":[],"mappings":"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","sourcesContent":["import { buildPropertyMapping, sanitizeExpression } from \"../../core/expression-utils\";\n\nimport { InputManager } from \"./base\";\n\nexport class ExpressionFilterInputManager extends InputManager {\n\tprivate compiledFunc: ((...args: unknown[]) => boolean) | null = null;\n\n\tprivate propertyMapping = new Map<string, string>();\n\n\tprivate lastWarnedExpression: string | null = null;\n\n\tconstructor(\n\t\tparentEl: HTMLElement,\n\t\tcssPrefix: string,\n\t\tonFilterChange: () => void,\n\t\tinitiallyVisible: boolean = false,\n\t\tplaceholder: string = \"Status === 'Done'\",\n\t\tonHide?: () => void,\n\t\tdebounceMs?: number\n\t) {\n\t\tsuper(parentEl, placeholder, cssPrefix, onFilterChange, initiallyVisible, onHide, debounceMs);\n\t\tthis.cssClass = `${cssPrefix}-expression-input`;\n\t\tif (this.inputEl) {\n\t\t\tthis.inputEl.className = this.cssClass;\n\t\t}\n\t}\n\n\tprotected updateFilterValue(filterValue: string): void {\n\t\tsuper.updateFilterValue(filterValue);\n\n\t\tthis.compiledFunc = null;\n\n\t\tthis.propertyMapping.clear();\n\n\t\tthis.lastWarnedExpression = null;\n\t}\n\n\tshouldInclude(event: { meta?: Record<string, unknown> }): boolean {\n\t\tif (!this.currentValue) return true;\n\n\t\tconst frontmatter = event.meta || {};\n\n\t\ttry {\n\t\t\tconst currentKeys = new Set(Object.keys(frontmatter));\n\n\t\t\tconst existingKeys = new Set(this.propertyMapping.keys());\n\n\t\t\tconst newKeys = [...currentKeys].filter((key) => !existingKeys.has(key));\n\n\t\t\tif (newKeys.length > 0) {\n\t\t\t\tconst allKeys = new Set([...existingKeys, ...currentKeys]);\n\n\t\t\t\tthis.propertyMapping = buildPropertyMapping(Array.from(allKeys));\n\n\t\t\t\tthis.compiledFunc = null;\n\t\t\t}\n\n\t\t\tif (!this.compiledFunc) {\n\t\t\t\tconst sanitized = sanitizeExpression(this.currentValue, this.propertyMapping);\n\n\t\t\t\tconst params = Array.from(this.propertyMapping.values());\n\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-implied-eval -- Dynamic function creation for expression evaluation with sanitized input\n\t\t\t\tthis.compiledFunc = new Function(...params, `\"use strict\"; return ${sanitized};`) as (\n\t\t\t\t\t...args: unknown[]\n\t\t\t\t) => boolean;\n\t\t\t}\n\n\t\t\tconst values = Array.from(this.propertyMapping.keys()).map(\n\t\t\t\t(key) => frontmatter[key] ?? undefined\n\t\t\t);\n\n\t\t\tconst result = this.compiledFunc(...values);\n\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tif (error instanceof ReferenceError) {\n\t\t\t\tconst hasInequality = this.currentValue.includes(\"!==\") || this.currentValue.includes(\"!=\");\n\n\t\t\t\treturn hasInequality;\n\t\t\t}\n\n\t\t\tif (this.lastWarnedExpression !== this.currentValue) {\n\t\t\t\tconsole.warn(\"Invalid filter expression:\", this.currentValue, error);\n\n\t\t\t\tthis.lastWarnedExpression = this.currentValue;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export * from "./base";
2
+ export * from "./expression";
3
+ export * from "./search";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/input-managers/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from "./base";
2
+ export * from "./expression";
3
+ export * from "./search";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/input-managers/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC","sourcesContent":["export * from \"./base\";\nexport * from \"./expression\";\nexport * from \"./search\";\n"]}
@@ -0,0 +1,6 @@
1
+ import { InputManager } from "./base";
2
+ export declare class SearchFilterInputManager extends InputManager {
3
+ constructor(parentEl: HTMLElement, cssPrefix: string, onFilterChange: () => void, initiallyVisible?: boolean, placeholder?: string, onHide?: () => void, debounceMs?: number);
4
+ shouldInclude(value: string): boolean;
5
+ }
6
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/components/input-managers/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,qBAAa,wBAAyB,SAAQ,YAAY;gBAExD,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,IAAI,EAC1B,gBAAgB,GAAE,OAAe,EACjC,WAAW,GAAE,MAAqB,EAClC,MAAM,CAAC,EAAE,MAAM,IAAI,EACnB,UAAU,CAAC,EAAE,MAAM;IASpB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;CAKrC"}
@@ -0,0 +1,16 @@
1
+ import { InputManager } from "./base";
2
+ export class SearchFilterInputManager extends InputManager {
3
+ constructor(parentEl, cssPrefix, onFilterChange, initiallyVisible = false, placeholder = "Search ...", onHide, debounceMs) {
4
+ super(parentEl, placeholder, cssPrefix, onFilterChange, initiallyVisible, onHide, debounceMs);
5
+ this.cssClass = `${cssPrefix}-search-input`;
6
+ if (this.inputEl) {
7
+ this.inputEl.className = this.cssClass;
8
+ }
9
+ }
10
+ shouldInclude(value) {
11
+ if (!this.currentValue)
12
+ return true;
13
+ return value.toLowerCase().includes(this.currentValue.toLowerCase());
14
+ }
15
+ }
16
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/components/input-managers/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,OAAO,wBAAyB,SAAQ,YAAY;IACzD,YACC,QAAqB,EACrB,SAAiB,EACjB,cAA0B,EAC1B,mBAA4B,KAAK,EACjC,cAAsB,YAAY,EAClC,MAAmB,EACnB,UAAmB;QAEnB,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;QAC9F,IAAI,CAAC,QAAQ,GAAG,GAAG,SAAS,eAAe,CAAC;QAC5C,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC;QACxC,CAAC;IACF,CAAC;IAED,aAAa,CAAC,KAAa;QAC1B,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC;QAEpC,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC;IACtE,CAAC;CACD","sourcesContent":["import { InputManager } from \"./base\";\n\nexport class SearchFilterInputManager extends InputManager {\n\tconstructor(\n\t\tparentEl: HTMLElement,\n\t\tcssPrefix: string,\n\t\tonFilterChange: () => void,\n\t\tinitiallyVisible: boolean = false,\n\t\tplaceholder: string = \"Search ...\",\n\t\tonHide?: () => void,\n\t\tdebounceMs?: number\n\t) {\n\t\tsuper(parentEl, placeholder, cssPrefix, onFilterChange, initiallyVisible, onHide, debounceMs);\n\t\tthis.cssClass = `${cssPrefix}-search-input`;\n\t\tif (this.inputEl) {\n\t\t\tthis.inputEl.className = this.cssClass;\n\t\t}\n\t}\n\n\tshouldInclude(value: string): boolean {\n\t\tif (!this.currentValue) return true;\n\n\t\treturn value.toLowerCase().includes(this.currentValue.toLowerCase());\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/core/evaluator/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,MAAM,CAAC;AAI1D,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,8BAAsB,aAAa,CAAC,KAAK,SAAS,QAAQ,EAAE,SAAS;IACpE,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,CAAM;IAC9B,OAAO,CAAC,iBAAiB,CAA2D;IACpF,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,YAAY,CAA6B;gBAErC,aAAa,EAAE,eAAe,CAAC,SAAS,CAAC;IAQrD,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,QAAQ,EAAE,SAAS,GAAG,KAAK,EAAE;IAE7D,OAAO,IAAI,IAAI;IAMf,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;IA+BlF,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO;CAGvC"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/core/evaluator/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,MAAM,CAAC;AAI1D,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,8BAAsB,aAAa,CAAC,KAAK,SAAS,QAAQ,EAAE,SAAS;IACpE,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,CAAM;IAC9B,OAAO,CAAC,iBAAiB,CAA2D;IACpF,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,YAAY,CAA6B;gBAErC,aAAa,EAAE,eAAe,CAAC,SAAS,CAAC;IAQrD,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,QAAQ,EAAE,SAAS,GAAG,KAAK,EAAE;IAE7D,OAAO,IAAI,IAAI;IAMf,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;IA2ClF,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO;CAGvC"}
@@ -26,8 +26,16 @@ export class BaseEvaluator {
26
26
  return false;
27
27
  }
28
28
  try {
29
- if (this.propertyMapping.size === 0) {
30
- this.propertyMapping = buildPropertyMapping(Object.keys(frontmatter));
29
+ // Progressively build property mapping as we encounter new properties
30
+ const currentKeys = new Set(Object.keys(frontmatter));
31
+ const existingKeys = new Set(this.propertyMapping.keys());
32
+ const newKeys = [...currentKeys].filter((key) => !existingKeys.has(key));
33
+ // If new properties are found, rebuild the mapping and invalidate compiled functions
34
+ if (newKeys.length > 0) {
35
+ const allKeys = new Set([...existingKeys, ...currentKeys]);
36
+ this.propertyMapping = buildPropertyMapping(Array.from(allKeys));
37
+ // Clear compiled functions since property mapping changed
38
+ this.compiledFunctions.clear();
31
39
  }
32
40
  let compiledFunc = this.compiledFunctions.get(rule.id);
33
41
  if (!compiledFunc) {
@@ -36,7 +44,8 @@ export class BaseEvaluator {
36
44
  compiledFunc = new Function(...params, `"use strict"; return ${sanitized};`);
37
45
  this.compiledFunctions.set(rule.id, compiledFunc);
38
46
  }
39
- const values = Array.from(this.propertyMapping.keys()).map((key) => frontmatter[key]);
47
+ // Use undefined for missing properties instead of letting them be undefined implicitly
48
+ const values = Array.from(this.propertyMapping.keys()).map((key) => { var _a; return (_a = frontmatter[key]) !== null && _a !== void 0 ? _a : undefined; });
40
49
  const result = compiledFunc(...values);
41
50
  return result === true;
42
51
  }
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/core/evaluator/base.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAQ/E;;;GAGG;AACH,MAAM,OAAgB,aAAa;IAMlC,YAAY,aAAyC;QAL3C,UAAK,GAAY,EAAE,CAAC;QACtB,sBAAiB,GAAG,IAAI,GAAG,EAAgD,CAAC;QAC5E,oBAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC5C,iBAAY,GAAwB,IAAI,CAAC;QAGhD,IAAI,CAAC,YAAY,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,EAAE;YACxD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACzC,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;YAC/B,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAC9B,CAAC,CAAC,CAAC;IACJ,CAAC;IAID,OAAO;;QACN,MAAA,IAAI,CAAC,YAAY,0CAAE,WAAW,EAAE,CAAC;QACjC,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;IAES,YAAY,CAAC,IAAW,EAAE,WAAoC;QACvE,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACvC,OAAO,KAAK,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACJ,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACrC,IAAI,CAAC,eAAe,GAAG,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;YACvE,CAAC;YAED,IAAI,YAAY,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEvD,IAAI,CAAC,YAAY,EAAE,CAAC;gBACnB,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;gBAC5E,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC;gBACzD,YAAY,GAAG,IAAI,QAAQ,CAAC,GAAG,MAAM,EAAE,wBAAwB,SAAS,GAAG,CAE/D,CAAC;gBACb,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;YACnD,CAAC;YAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;YACtF,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,MAAM,CAAC,CAAC;YAEvC,OAAO,MAAM,KAAK,IAAI,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,IAAI,CAAC,uBAAuB,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YACzE,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAES,QAAQ,CAAC,KAAU;QAC5B,OAAO,KAAK,KAAK,IAAI,CAAC;IACvB,CAAC;CACD","sourcesContent":["import type { BehaviorSubject, Subscription } from \"rxjs\";\n\nimport { buildPropertyMapping, sanitizeExpression } from \"../expression-utils\";\n\nexport interface BaseRule {\n\tid: string;\n\texpression: string;\n\tenabled: boolean;\n}\n\n/**\n * Generic base class for evaluating JavaScript expressions against frontmatter objects.\n * Provides reactive compilation of rules via RxJS subscription and safe evaluation.\n */\nexport abstract class BaseEvaluator<TRule extends BaseRule, TSettings> {\n\tprotected rules: TRule[] = [];\n\tprivate compiledFunctions = new Map<string, ((...args: any[]) => boolean) | null>();\n\tprivate propertyMapping = new Map<string, string>();\n\tprivate subscription: Subscription | null = null;\n\n\tconstructor(settingsStore: BehaviorSubject<TSettings>) {\n\t\tthis.subscription = settingsStore.subscribe((settings) => {\n\t\t\tthis.rules = this.extractRules(settings);\n\t\t\tthis.compiledFunctions.clear();\n\t\t\tthis.propertyMapping.clear();\n\t\t});\n\t}\n\n\tprotected abstract extractRules(settings: TSettings): TRule[];\n\n\tdestroy(): void {\n\t\tthis.subscription?.unsubscribe();\n\t\tthis.compiledFunctions.clear();\n\t\tthis.propertyMapping.clear();\n\t}\n\n\tprotected evaluateRule(rule: TRule, frontmatter: Record<string, unknown>): boolean {\n\t\tif (!rule.enabled || !rule.expression) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\tif (this.propertyMapping.size === 0) {\n\t\t\t\tthis.propertyMapping = buildPropertyMapping(Object.keys(frontmatter));\n\t\t\t}\n\n\t\t\tlet compiledFunc = this.compiledFunctions.get(rule.id);\n\n\t\t\tif (!compiledFunc) {\n\t\t\t\tconst sanitized = sanitizeExpression(rule.expression, this.propertyMapping);\n\t\t\t\tconst params = Array.from(this.propertyMapping.values());\n\t\t\t\tcompiledFunc = new Function(...params, `\"use strict\"; return ${sanitized};`) as (\n\t\t\t\t\t...args: any[]\n\t\t\t\t) => boolean;\n\t\t\t\tthis.compiledFunctions.set(rule.id, compiledFunc);\n\t\t\t}\n\n\t\t\tconst values = Array.from(this.propertyMapping.keys()).map((key) => frontmatter[key]);\n\t\t\tconst result = compiledFunc(...values);\n\n\t\t\treturn result === true;\n\t\t} catch (error) {\n\t\t\tconsole.warn(`Invalid expression (${rule.id}):`, rule.expression, error);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprotected isTruthy(value: any): boolean {\n\t\treturn value === true;\n\t}\n}\n"]}
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/core/evaluator/base.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BehaviorSubject, Subscription } from \"rxjs\";\n\nimport { buildPropertyMapping, sanitizeExpression } from \"../expression-utils\";\n\nexport interface BaseRule {\n\tid: string;\n\texpression: string;\n\tenabled: boolean;\n}\n\n/**\n * Generic base class for evaluating JavaScript expressions against frontmatter objects.\n * Provides reactive compilation of rules via RxJS subscription and safe evaluation.\n */\nexport abstract class BaseEvaluator<TRule extends BaseRule, TSettings> {\n\tprotected rules: TRule[] = [];\n\tprivate compiledFunctions = new Map<string, ((...args: any[]) => boolean) | null>();\n\tprivate propertyMapping = new Map<string, string>();\n\tprivate subscription: Subscription | null = null;\n\n\tconstructor(settingsStore: BehaviorSubject<TSettings>) {\n\t\tthis.subscription = settingsStore.subscribe((settings) => {\n\t\t\tthis.rules = this.extractRules(settings);\n\t\t\tthis.compiledFunctions.clear();\n\t\t\tthis.propertyMapping.clear();\n\t\t});\n\t}\n\n\tprotected abstract extractRules(settings: TSettings): TRule[];\n\n\tdestroy(): void {\n\t\tthis.subscription?.unsubscribe();\n\t\tthis.compiledFunctions.clear();\n\t\tthis.propertyMapping.clear();\n\t}\n\n\tprotected evaluateRule(rule: TRule, frontmatter: Record<string, unknown>): boolean {\n\t\tif (!rule.enabled || !rule.expression) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Progressively build property mapping as we encounter new properties\n\t\t\tconst currentKeys = new Set(Object.keys(frontmatter));\n\t\t\tconst existingKeys = new Set(this.propertyMapping.keys());\n\t\t\tconst newKeys = [...currentKeys].filter((key) => !existingKeys.has(key));\n\n\t\t\t// If new properties are found, rebuild the mapping and invalidate compiled functions\n\t\t\tif (newKeys.length > 0) {\n\t\t\t\tconst allKeys = new Set([...existingKeys, ...currentKeys]);\n\t\t\t\tthis.propertyMapping = buildPropertyMapping(Array.from(allKeys));\n\t\t\t\t// Clear compiled functions since property mapping changed\n\t\t\t\tthis.compiledFunctions.clear();\n\t\t\t}\n\n\t\t\tlet compiledFunc = this.compiledFunctions.get(rule.id);\n\n\t\t\tif (!compiledFunc) {\n\t\t\t\tconst sanitized = sanitizeExpression(rule.expression, this.propertyMapping);\n\t\t\t\tconst params = Array.from(this.propertyMapping.values());\n\t\t\t\tcompiledFunc = new Function(...params, `\"use strict\"; return ${sanitized};`) as (\n\t\t\t\t\t...args: any[]\n\t\t\t\t) => boolean;\n\t\t\t\tthis.compiledFunctions.set(rule.id, compiledFunc);\n\t\t\t}\n\n\t\t\t// Use undefined for missing properties instead of letting them be undefined implicitly\n\t\t\tconst values = Array.from(this.propertyMapping.keys()).map(\n\t\t\t\t(key) => frontmatter[key] ?? undefined\n\t\t\t);\n\t\t\tconst result = compiledFunc(...values);\n\n\t\t\treturn result === true;\n\t\t} catch (error) {\n\t\t\tconsole.warn(`Invalid expression (${rule.id}):`, rule.expression, error);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprotected isTruthy(value: any): boolean {\n\t\treturn value === true;\n\t}\n}\n"]}
@@ -0,0 +1,38 @@
1
+ export type Frontmatter = Record<string, unknown>;
2
+ export interface FrontmatterChange {
3
+ key: string;
4
+ oldValue: unknown;
5
+ newValue: unknown;
6
+ changeType: "added" | "modified" | "deleted";
7
+ }
8
+ export interface FrontmatterDiff {
9
+ hasChanges: boolean;
10
+ changes: FrontmatterChange[];
11
+ added: FrontmatterChange[];
12
+ modified: FrontmatterChange[];
13
+ deleted: FrontmatterChange[];
14
+ }
15
+ /**
16
+ * Compares two frontmatter objects and returns a detailed diff.
17
+ * Excludes specified properties from comparison (e.g., Prisma-managed properties).
18
+ *
19
+ * @param oldFrontmatter - The original frontmatter
20
+ * @param newFrontmatter - The updated frontmatter
21
+ * @param excludeProps - Set of property keys to exclude from comparison
22
+ * @returns Detailed diff with categorized changes
23
+ */
24
+ export declare function compareFrontmatter(oldFrontmatter: Frontmatter, newFrontmatter: Frontmatter, excludeProps?: Set<string>): FrontmatterDiff;
25
+ /**
26
+ * Merges multiple frontmatter diffs into a single accumulated diff.
27
+ * Later diffs override earlier ones for the same key.
28
+ *
29
+ * @param diffs - Array of diffs to merge (in chronological order)
30
+ * @returns A single merged diff containing all accumulated changes
31
+ */
32
+ export declare function mergeFrontmatterDiffs(diffs: FrontmatterDiff[]): FrontmatterDiff;
33
+ /**
34
+ * Formats a frontmatter change for display in a modal.
35
+ * Returns a human-readable string describing the change.
36
+ */
37
+ export declare function formatChangeForDisplay(change: FrontmatterChange): string;
38
+ //# sourceMappingURL=frontmatter-diff.d.ts.map
@@ -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"}