@real1ty-obsidian-plugins/utils 2.11.0 → 2.14.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 (75) hide show
  1. package/dist/components/index.d.ts +2 -0
  2. package/dist/components/index.d.ts.map +1 -0
  3. package/dist/components/index.js +2 -0
  4. package/dist/components/index.js.map +1 -0
  5. package/dist/components/input-managers/base.d.ts +30 -0
  6. package/dist/components/input-managers/base.d.ts.map +1 -0
  7. package/dist/components/input-managers/base.js +115 -0
  8. package/dist/components/input-managers/base.js.map +1 -0
  9. package/dist/components/input-managers/expression.d.ts +12 -0
  10. package/dist/components/input-managers/expression.d.ts.map +1 -0
  11. package/dist/components/input-managers/expression.js +56 -0
  12. package/dist/components/input-managers/expression.js.map +1 -0
  13. package/dist/components/input-managers/index.d.ts +4 -0
  14. package/dist/components/input-managers/index.d.ts.map +1 -0
  15. package/dist/components/input-managers/index.js +4 -0
  16. package/dist/components/input-managers/index.js.map +1 -0
  17. package/dist/components/input-managers/search.d.ts +6 -0
  18. package/dist/components/input-managers/search.d.ts.map +1 -0
  19. package/dist/components/input-managers/search.js +16 -0
  20. package/dist/components/input-managers/search.js.map +1 -0
  21. package/dist/core/evaluator/base.d.ts.map +1 -1
  22. package/dist/core/evaluator/base.js +12 -3
  23. package/dist/core/evaluator/base.js.map +1 -1
  24. package/dist/core/index.d.ts +1 -0
  25. package/dist/core/index.d.ts.map +1 -1
  26. package/dist/core/index.js +1 -0
  27. package/dist/core/index.js.map +1 -1
  28. package/dist/core/property-renderer.d.ts +9 -0
  29. package/dist/core/property-renderer.d.ts.map +1 -0
  30. package/dist/core/property-renderer.js +42 -0
  31. package/dist/core/property-renderer.js.map +1 -0
  32. package/dist/file/file-utils.d.ts +28 -0
  33. package/dist/file/file-utils.d.ts.map +1 -0
  34. package/dist/file/file-utils.js +55 -0
  35. package/dist/file/file-utils.js.map +1 -0
  36. package/dist/file/file.d.ts +51 -1
  37. package/dist/file/file.d.ts.map +1 -1
  38. package/dist/file/file.js +69 -10
  39. package/dist/file/file.js.map +1 -1
  40. package/dist/file/index.d.ts +1 -0
  41. package/dist/file/index.d.ts.map +1 -1
  42. package/dist/file/index.js +1 -0
  43. package/dist/file/index.js.map +1 -1
  44. package/dist/file/link-parser.d.ts +28 -0
  45. package/dist/file/link-parser.d.ts.map +1 -1
  46. package/dist/file/link-parser.js +59 -0
  47. package/dist/file/link-parser.js.map +1 -1
  48. package/dist/index.d.ts +1 -0
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +2 -0
  51. package/dist/index.js.map +1 -1
  52. package/dist/string/filename-utils.d.ts +46 -0
  53. package/dist/string/filename-utils.d.ts.map +1 -0
  54. package/dist/string/filename-utils.js +65 -0
  55. package/dist/string/filename-utils.js.map +1 -0
  56. package/dist/string/index.d.ts +1 -0
  57. package/dist/string/index.d.ts.map +1 -1
  58. package/dist/string/index.js +1 -0
  59. package/dist/string/index.js.map +1 -1
  60. package/package.json +1 -1
  61. package/src/components/index.ts +1 -0
  62. package/src/components/input-managers/base.ts +150 -0
  63. package/src/components/input-managers/expression.ts +92 -0
  64. package/src/components/input-managers/index.ts +3 -0
  65. package/src/components/input-managers/search.ts +25 -0
  66. package/src/core/evaluator/base.ts +15 -3
  67. package/src/core/index.ts +1 -0
  68. package/src/core/property-renderer.ts +62 -0
  69. package/src/file/file-utils.ts +67 -0
  70. package/src/file/file.ts +90 -8
  71. package/src/file/index.ts +1 -0
  72. package/src/file/link-parser.ts +71 -0
  73. package/src/index.ts +2 -0
  74. package/src/string/filename-utils.ts +77 -0
  75. package/src/string/index.ts +1 -0
@@ -0,0 +1,2 @@
1
+ export * from "./input-managers";
2
+ //# 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,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./input-managers";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC","sourcesContent":["export * 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"]}
@@ -4,5 +4,6 @@ export * from "./evaluator";
4
4
  export * from "./expression-utils";
5
5
  export * from "./frontmatter-value";
6
6
  export * from "./generate";
7
+ export * from "./property-renderer";
7
8
  export * from "./validation";
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC"}
@@ -4,5 +4,6 @@ export * from "./evaluator";
4
4
  export * from "./expression-utils";
5
5
  export * from "./frontmatter-value";
6
6
  export * from "./generate";
7
+ export * from "./property-renderer";
7
8
  export * from "./validation";
8
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC","sourcesContent":["export * from \"./color-utils\";\nexport * from \"./css-utils\";\nexport * from \"./evaluator\";\nexport * from \"./expression-utils\";\nexport * from \"./frontmatter-value\";\nexport * from \"./generate\";\nexport * from \"./validation\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC","sourcesContent":["export * from \"./color-utils\";\nexport * from \"./css-utils\";\nexport * from \"./evaluator\";\nexport * from \"./expression-utils\";\nexport * from \"./frontmatter-value\";\nexport * from \"./generate\";\nexport * from \"./property-renderer\";\nexport * from \"./validation\";\n"]}
@@ -0,0 +1,9 @@
1
+ export interface PropertyRendererConfig {
2
+ createLink: (text: string, path: string, isObsidianLink: boolean) => HTMLElement;
3
+ createText: (text: string) => HTMLElement | Text;
4
+ createSeparator?: () => HTMLElement | Text;
5
+ }
6
+ export declare function renderPropertyValue(container: HTMLElement, value: any, config: PropertyRendererConfig): void;
7
+ export declare function createTextNode(text: string): Text;
8
+ export declare function createDefaultSeparator(): Text;
9
+ //# sourceMappingURL=property-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-renderer.d.ts","sourceRoot":"","sources":["../../src/core/property-renderer.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,sBAAsB;IACtC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,KAAK,WAAW,CAAC;IACjF,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,GAAG,IAAI,CAAC;IACjD,eAAe,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;CAC3C;AAED,wBAAgB,mBAAmB,CAClC,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,sBAAsB,GAC5B,IAAI,CAqBN;AAsBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
@@ -0,0 +1,42 @@
1
+ import { getObsidianLinkAlias, getObsidianLinkPath, isObsidianLink } from "../file/link-parser";
2
+ export function renderPropertyValue(container, value, config) {
3
+ // Handle arrays - render each item separately
4
+ if (Array.isArray(value)) {
5
+ const hasClickableLinks = value.some(isObsidianLink);
6
+ if (hasClickableLinks) {
7
+ for (let index = 0; index < value.length; index++) {
8
+ if (index > 0 && config.createSeparator) {
9
+ container.appendChild(config.createSeparator());
10
+ }
11
+ renderSingleValue(container, value[index], config);
12
+ }
13
+ }
14
+ else {
15
+ // Plain array - just join with commas
16
+ const textNode = config.createText(value.join(", "));
17
+ container.appendChild(textNode);
18
+ }
19
+ return;
20
+ }
21
+ renderSingleValue(container, value, config);
22
+ }
23
+ function renderSingleValue(container, value, config) {
24
+ const stringValue = String(value).trim();
25
+ if (isObsidianLink(stringValue)) {
26
+ const displayText = getObsidianLinkAlias(stringValue);
27
+ const linkPath = getObsidianLinkPath(stringValue);
28
+ const link = config.createLink(displayText, linkPath, true);
29
+ container.appendChild(link);
30
+ return;
31
+ }
32
+ // Regular text
33
+ const textNode = config.createText(stringValue);
34
+ container.appendChild(textNode);
35
+ }
36
+ export function createTextNode(text) {
37
+ return document.createTextNode(text);
38
+ }
39
+ export function createDefaultSeparator() {
40
+ return document.createTextNode(", ");
41
+ }
42
+ //# sourceMappingURL=property-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-renderer.js","sourceRoot":"","sources":["../../src/core/property-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAQhG,MAAM,UAAU,mBAAmB,CAClC,SAAsB,EACtB,KAAU,EACV,MAA8B;IAE9B,8CAA8C;IAC9C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAErD,IAAI,iBAAiB,EAAE,CAAC;YACvB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;gBACnD,IAAI,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;oBACzC,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC;gBACjD,CAAC;gBACD,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;YACpD,CAAC;QACF,CAAC;aAAM,CAAC;YACP,sCAAsC;YACtC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACrD,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;QACD,OAAO;IACR,CAAC;IAED,iBAAiB,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,iBAAiB,CACzB,SAAsB,EACtB,KAAU,EACV,MAA8B;IAE9B,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IAEzC,IAAI,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC;QACjC,MAAM,WAAW,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;QACtD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC5D,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO;IACR,CAAC;IAED,eAAe;IACf,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAChD,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IAC1C,OAAO,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,sBAAsB;IACrC,OAAO,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC","sourcesContent":["import { getObsidianLinkAlias, getObsidianLinkPath, isObsidianLink } from \"../file/link-parser\";\n\nexport interface PropertyRendererConfig {\n\tcreateLink: (text: string, path: string, isObsidianLink: boolean) => HTMLElement;\n\tcreateText: (text: string) => HTMLElement | Text;\n\tcreateSeparator?: () => HTMLElement | Text;\n}\n\nexport function renderPropertyValue(\n\tcontainer: HTMLElement,\n\tvalue: any,\n\tconfig: PropertyRendererConfig\n): void {\n\t// Handle arrays - render each item separately\n\tif (Array.isArray(value)) {\n\t\tconst hasClickableLinks = value.some(isObsidianLink);\n\n\t\tif (hasClickableLinks) {\n\t\t\tfor (let index = 0; index < value.length; index++) {\n\t\t\t\tif (index > 0 && config.createSeparator) {\n\t\t\t\t\tcontainer.appendChild(config.createSeparator());\n\t\t\t\t}\n\t\t\t\trenderSingleValue(container, value[index], config);\n\t\t\t}\n\t\t} else {\n\t\t\t// Plain array - just join with commas\n\t\t\tconst textNode = config.createText(value.join(\", \"));\n\t\t\tcontainer.appendChild(textNode);\n\t\t}\n\t\treturn;\n\t}\n\n\trenderSingleValue(container, value, config);\n}\n\nfunction renderSingleValue(\n\tcontainer: HTMLElement,\n\tvalue: any,\n\tconfig: PropertyRendererConfig\n): void {\n\tconst stringValue = String(value).trim();\n\n\tif (isObsidianLink(stringValue)) {\n\t\tconst displayText = getObsidianLinkAlias(stringValue);\n\t\tconst linkPath = getObsidianLinkPath(stringValue);\n\t\tconst link = config.createLink(displayText, linkPath, true);\n\t\tcontainer.appendChild(link);\n\t\treturn;\n\t}\n\n\t// Regular text\n\tconst textNode = config.createText(stringValue);\n\tcontainer.appendChild(textNode);\n}\n\nexport function createTextNode(text: string): Text {\n\treturn document.createTextNode(text);\n}\n\nexport function createDefaultSeparator(): Text {\n\treturn document.createTextNode(\", \");\n}\n"]}
@@ -0,0 +1,28 @@
1
+ import type { App } from "obsidian";
2
+ import { TFile } from "obsidian";
3
+ /**
4
+ * Gets a TFile by path or throws an error if not found.
5
+ * Useful when you need to ensure a file exists before proceeding.
6
+ */
7
+ export declare const getTFileOrThrow: (app: App, path: string) => TFile;
8
+ /**
9
+ * Executes an operation on a file's frontmatter.
10
+ * Wrapper around Obsidian's processFrontMatter for more concise usage.
11
+ */
12
+ export declare const withFrontmatter: (app: App, file: TFile, update: (fm: Record<string, unknown>) => void) => Promise<void>;
13
+ /**
14
+ * Creates a backup copy of a file's frontmatter.
15
+ * Useful for undo/redo operations or temporary modifications.
16
+ */
17
+ export declare const backupFrontmatter: (app: App, file: TFile) => Promise<Record<string, unknown>>;
18
+ /**
19
+ * Restores a file's frontmatter from a backup.
20
+ * Clears existing frontmatter and replaces with the backup.
21
+ */
22
+ export declare const restoreFrontmatter: (app: App, file: TFile, original: Record<string, unknown>) => Promise<void>;
23
+ /**
24
+ * Extracts the content that appears after the frontmatter section.
25
+ * Returns the entire content if no frontmatter is found.
26
+ */
27
+ export declare const extractContentAfterFrontmatter: (fullContent: string) => string;
28
+ //# sourceMappingURL=file-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/file/file-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,KAAK,GAAG,EAAE,MAAM,MAAM,KAAG,KAIxD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAC3B,KAAK,GAAG,EACR,MAAM,KAAK,EACX,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,kBACO,CAAC;AAEtD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAU,KAAK,GAAG,EAAE,MAAM,KAAK,qCAM5D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC9B,KAAK,GAAG,EACR,MAAM,KAAK,EACX,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,kBAO/B,CAAC;AAEJ;;;GAGG;AACH,eAAO,MAAM,8BAA8B,GAAI,aAAa,MAAM,KAAG,MAWpE,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { __awaiter } from "tslib";
2
+ import { TFile } from "obsidian";
3
+ /**
4
+ * Gets a TFile by path or throws an error if not found.
5
+ * Useful when you need to ensure a file exists before proceeding.
6
+ */
7
+ export const getTFileOrThrow = (app, path) => {
8
+ const f = app.vault.getAbstractFileByPath(path);
9
+ if (!(f instanceof TFile))
10
+ throw new Error(`File not found: ${path}`);
11
+ return f;
12
+ };
13
+ /**
14
+ * Executes an operation on a file's frontmatter.
15
+ * Wrapper around Obsidian's processFrontMatter for more concise usage.
16
+ */
17
+ export const withFrontmatter = (app, file, update) => __awaiter(void 0, void 0, void 0, function* () { return app.fileManager.processFrontMatter(file, update); });
18
+ /**
19
+ * Creates a backup copy of a file's frontmatter.
20
+ * Useful for undo/redo operations or temporary modifications.
21
+ */
22
+ export const backupFrontmatter = (app, file) => __awaiter(void 0, void 0, void 0, function* () {
23
+ let copy = {};
24
+ yield withFrontmatter(app, file, (fm) => {
25
+ copy = Object.assign({}, fm);
26
+ });
27
+ return copy;
28
+ });
29
+ /**
30
+ * Restores a file's frontmatter from a backup.
31
+ * Clears existing frontmatter and replaces with the backup.
32
+ */
33
+ export const restoreFrontmatter = (app, file, original) => __awaiter(void 0, void 0, void 0, function* () {
34
+ return withFrontmatter(app, file, (fm) => {
35
+ for (const k of Object.keys(fm)) {
36
+ delete fm[k];
37
+ }
38
+ Object.assign(fm, original);
39
+ });
40
+ });
41
+ /**
42
+ * Extracts the content that appears after the frontmatter section.
43
+ * Returns the entire content if no frontmatter is found.
44
+ */
45
+ export const extractContentAfterFrontmatter = (fullContent) => {
46
+ const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n/;
47
+ const match = fullContent.match(frontmatterRegex);
48
+ if (match) {
49
+ // Return content after frontmatter
50
+ return fullContent.substring(match.index + match[0].length);
51
+ }
52
+ // If no frontmatter found, return the entire content
53
+ return fullContent;
54
+ };
55
+ //# sourceMappingURL=file-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../src/file/file-utils.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAQ,EAAE,IAAY,EAAS,EAAE;IAChE,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;IACtE,OAAO,CAAC,CAAC;AACV,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC9B,GAAQ,EACR,IAAW,EACX,MAA6C,EAC5C,EAAE,kDAAC,OAAA,GAAG,CAAC,WAAW,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA,GAAA,CAAC;AAEtD;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAO,GAAQ,EAAE,IAAW,EAAE,EAAE;IAChE,IAAI,IAAI,GAA4B,EAAE,CAAC;IACvC,MAAM,eAAe,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;QACvC,IAAI,qBAAQ,EAAE,CAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACb,CAAC,CAAA,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CACjC,GAAQ,EACR,IAAW,EACX,QAAiC,EAChC,EAAE;IACH,OAAA,eAAe,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;QACjC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACjC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAA;EAAA,CAAC;AAEJ;;;GAGG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,WAAmB,EAAU,EAAE;IAC7E,MAAM,gBAAgB,GAAG,+BAA+B,CAAC;IACzD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAElD,IAAI,KAAK,EAAE,CAAC;QACX,mCAAmC;QACnC,OAAO,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,KAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC9D,CAAC;IAED,qDAAqD;IACrD,OAAO,WAAW,CAAC;AACpB,CAAC,CAAC","sourcesContent":["import type { App } from \"obsidian\";\nimport { TFile } from \"obsidian\";\n\n/**\n * Gets a TFile by path or throws an error if not found.\n * Useful when you need to ensure a file exists before proceeding.\n */\nexport const getTFileOrThrow = (app: App, path: string): TFile => {\n\tconst f = app.vault.getAbstractFileByPath(path);\n\tif (!(f instanceof TFile)) throw new Error(`File not found: ${path}`);\n\treturn f;\n};\n\n/**\n * Executes an operation on a file's frontmatter.\n * Wrapper around Obsidian's processFrontMatter for more concise usage.\n */\nexport const withFrontmatter = async (\n\tapp: App,\n\tfile: TFile,\n\tupdate: (fm: Record<string, unknown>) => void\n) => app.fileManager.processFrontMatter(file, update);\n\n/**\n * Creates a backup copy of a file's frontmatter.\n * Useful for undo/redo operations or temporary modifications.\n */\nexport const backupFrontmatter = async (app: App, file: TFile) => {\n\tlet copy: Record<string, unknown> = {};\n\tawait withFrontmatter(app, file, (fm) => {\n\t\tcopy = { ...fm };\n\t});\n\treturn copy;\n};\n\n/**\n * Restores a file's frontmatter from a backup.\n * Clears existing frontmatter and replaces with the backup.\n */\nexport const restoreFrontmatter = async (\n\tapp: App,\n\tfile: TFile,\n\toriginal: Record<string, unknown>\n) =>\n\twithFrontmatter(app, file, (fm) => {\n\t\tfor (const k of Object.keys(fm)) {\n\t\t\tdelete fm[k];\n\t\t}\n\t\tObject.assign(fm, original);\n\t});\n\n/**\n * Extracts the content that appears after the frontmatter section.\n * Returns the entire content if no frontmatter is found.\n */\nexport const extractContentAfterFrontmatter = (fullContent: string): string => {\n\tconst frontmatterRegex = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n/;\n\tconst match = fullContent.match(frontmatterRegex);\n\n\tif (match) {\n\t\t// Return content after frontmatter\n\t\treturn fullContent.substring(match.index! + match[0].length);\n\t}\n\n\t// If no frontmatter found, return the entire content\n\treturn fullContent;\n};\n"]}