mirror of
https://github.com/decaf-dev/obsidian-vault-explorer.git
synced 2026-07-22 10:10:31 +00:00
Property value loading (#80)
* docs: add more features * refactor: move to services * feat: update loadPropertyValue to handle edge cases * test: add typescript support for jest * refactor: remove version script * test: add test for loadPropertyValue * test: remove paths
This commit is contained in:
parent
831773b459
commit
8e863ada96
15 changed files with 386 additions and 92 deletions
|
|
@ -36,3 +36,11 @@ Features are what the software should do.
|
|||
| Set a favorite property | #settings |
|
||||
| Set text properties | #settings |
|
||||
| Set the log level | #settings |
|
||||
| When is a file deleted, refresh the view | |
|
||||
| When is the metadata of a file changes, refresh the view | |
|
||||
| When a file is renamed, refresh the view | |
|
||||
| When a file is created, refresh the view | |
|
||||
| When a file is modified, refresh the view | |
|
||||
| Refresh time variables every minute | |
|
||||
| When a setting changes, update the view | |
|
||||
| Move focus with left and right arrows | |
|
||||
|
|
|
|||
7
__mocks__/js-logger.ts
Normal file
7
__mocks__/js-logger.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export default {
|
||||
log: jest.fn(),
|
||||
info: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
error: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
};
|
||||
8
__mocks__/obsidian.ts
Normal file
8
__mocks__/obsidian.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
const DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
||||
const DATE_TIME_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/;
|
||||
|
||||
export const moment = jest.fn((date, formats, strict) => {
|
||||
return {
|
||||
isValid: jest.fn(() => DATE_REGEX.test(date) || DATE_TIME_REGEX.test(date)),
|
||||
};
|
||||
});
|
||||
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
8
jest.config.js
Normal file
8
jest.config.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
moduleNameMapper: {
|
||||
"^src/(.*)$": "<rootDir>/src/$1",
|
||||
},
|
||||
};
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
"scripts": {
|
||||
"dev": "node esbuild.config.mjs",
|
||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
||||
"test": "jest --config jest.config.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "DecafDev",
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
"devDependencies": {
|
||||
"@tsconfig/svelte": "^5.0.4",
|
||||
"@types/bun": "latest",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/lodash": "^4.17.0",
|
||||
"@types/node": "^16.11.6",
|
||||
"@typescript-eslint/eslint-plugin": "5.29.0",
|
||||
|
|
@ -21,8 +22,10 @@
|
|||
"builtin-modules": "3.3.0",
|
||||
"esbuild": "0.17.3",
|
||||
"esbuild-svelte": "^0.8.0",
|
||||
"jest": "^29.7.0",
|
||||
"obsidian": "latest",
|
||||
"svelte-preprocess": "^5.1.4",
|
||||
"ts-jest": "^29.1.4",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
getStartOfLastWeekMillis,
|
||||
getStartOfTodayMillis,
|
||||
getStartOfThisWeekMillis,
|
||||
} from "./services/time-utils";
|
||||
} from "../shared/services/time-utils";
|
||||
|
||||
let plugin: VaultExplorerPlugin;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { FrontMatterCache } from "obsidian";
|
||||
import { CheckboxFilterCondition, DateFilterCondition, ListFilterCondition, NumberFilterCondition, PropertyFilter, PropertyFilterGroup } from "src/types";
|
||||
import { FilterCondition, TextFilterCondition } from "src/types";
|
||||
import Logger from "js-logger";
|
||||
import { getEndOfDayMillis, getStartOfDayMillis, getTimeMillis, isDateSupported } from "../time-utils";
|
||||
|
||||
import { getEndOfDayMillis, getStartOfDayMillis, getTimeMillis } from "../../../shared/services/time-utils";
|
||||
import { loadPropertyValue } from "src/svelte/shared/services/property-utils";
|
||||
|
||||
//Tests
|
||||
//Group is enabled/disabled
|
||||
|
|
@ -48,56 +49,29 @@ const filterByProperty = (frontmatter: FrontMatterCache | undefined, filter: Pro
|
|||
const { propertyName, condition, value, type, matchWhenPropertyDNE } = filter;
|
||||
if (propertyName === "") return true;
|
||||
|
||||
let propertyValue: (string | string[] | boolean | number | null) = frontmatter?.[propertyName] ?? null;
|
||||
|
||||
if (type === "text") {
|
||||
//If the value is not a string, skip the filter
|
||||
if (propertyValue !== null && typeof propertyValue !== "string") {
|
||||
Logger.warn(`Property value is not a string: ${propertyValue}`);
|
||||
return true;
|
||||
}
|
||||
const propertyValue = loadPropertyValue<string>(frontmatter, propertyName, type);
|
||||
const doesMatch = doesTextMatchFilter(propertyValue, value, condition, matchWhenPropertyDNE);
|
||||
return doesMatch;
|
||||
} else if (type === "list") {
|
||||
if (propertyValue !== null && !Array.isArray(propertyValue)) {
|
||||
Logger.warn(`Property value is not an array: ${propertyValue}`);
|
||||
return true;
|
||||
}
|
||||
const compare = value.split(",").map((v) => v.trim()).filter((v) => v !== "");
|
||||
const doesMatch = doesListMatchFilter(propertyValue, compare, condition, matchWhenPropertyDNE);
|
||||
return doesMatch;
|
||||
} else if (type === "number") {
|
||||
if (propertyValue !== null && typeof propertyValue !== "number") {
|
||||
Logger.warn(`Property value is not a number: ${propertyValue}`);
|
||||
return true;
|
||||
}
|
||||
const propertyValue = loadPropertyValue<number>(frontmatter, propertyName, type);
|
||||
const compare = parseFloat(value);
|
||||
const doesMatch = doesNumberMatchFilter(propertyValue, compare, condition, matchWhenPropertyDNE);
|
||||
return doesMatch;
|
||||
} else if (type === "checkbox") {
|
||||
if (propertyValue !== null && typeof propertyValue !== "boolean") {
|
||||
Logger.warn(`Property value is not a boolean: ${propertyValue}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
const propertyValue = loadPropertyValue<boolean>(frontmatter, propertyName, type);
|
||||
const compare = value === "true";
|
||||
const doesMatch = doesCheckboxMatchFilter(propertyValue, compare, condition, matchWhenPropertyDNE);
|
||||
return doesMatch;
|
||||
|
||||
} else if (type === "date" || type === "datetime") {
|
||||
if (propertyValue !== null && typeof propertyValue !== "string") {
|
||||
Logger.warn(`Property value is not a string: ${propertyValue}`);
|
||||
return true;
|
||||
//In older versions of Obsidian, the date could be stored in the frontmatter
|
||||
//in an unsupported date format
|
||||
} else if (propertyValue !== null && !isDateSupported(propertyValue)) {
|
||||
Logger.warn(`Property value has unsupported date format: ${propertyValue}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
const propertyValue = loadPropertyValue<string>(frontmatter, propertyName, type);
|
||||
const doesMatch = doesDateMatchFilter(condition, propertyValue, value, matchWhenPropertyDNE);
|
||||
return doesMatch;
|
||||
|
||||
} else if (type === "list") {
|
||||
const propertyValue = loadPropertyValue<string[]>(frontmatter, propertyName, type);
|
||||
const compare = value.split(",").map((v) => v.trim()).filter((v) => v !== "");
|
||||
const doesMatch = doesListMatchFilter(propertyValue, compare, condition, matchWhenPropertyDNE);
|
||||
return doesMatch;
|
||||
} else {
|
||||
throw new Error(`Property filter type not supported: ${type}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { FrontMatterCache, TFile } from "obsidian";
|
||||
import { VaultExplorerPluginSettings } from "src/types";
|
||||
import { PropertyType, VaultExplorerPluginSettings } from "src/types";
|
||||
import { MarkdownFileRenderData } from "../types";
|
||||
import { getTimeMillis, isDateSupported } from "./time-utils";
|
||||
import { getTimeMillis, isDateSupported } from "../../shared/services/time-utils";
|
||||
import Logger from "js-logger";
|
||||
import { loadPropertyValue } from "src/svelte/shared/services/property-utils";
|
||||
|
||||
export const formatFileDataForRender = (settings: VaultExplorerPluginSettings, file: TFile, frontmatter: FrontMatterCache | undefined,): MarkdownFileRenderData => {
|
||||
const tags: string[] | null = loadPropertyValue(frontmatter, "tags", true);
|
||||
const tags: string[] | null = loadPropertyValue<string[]>(frontmatter, "tags", PropertyType.LIST);
|
||||
|
||||
const {
|
||||
createdDate: createdDateProp,
|
||||
|
|
@ -17,14 +18,14 @@ export const formatFileDataForRender = (settings: VaultExplorerPluginSettings, f
|
|||
custom3: custom3Prop,
|
||||
} = settings.properties;
|
||||
|
||||
const url: string | null = loadPropertyValue(frontmatter, urlProp);
|
||||
const favorite: string | null = loadPropertyValue(frontmatter, favoriteProp);
|
||||
const creationDate: string | null = loadPropertyValue(frontmatter, createdDateProp);
|
||||
const modifiedDate: string | null = loadPropertyValue(frontmatter, modifiedDateProp);
|
||||
const url: string | null = loadPropertyValue<string>(frontmatter, urlProp, PropertyType.TEXT);
|
||||
const favorite: boolean | null = loadPropertyValue<boolean>(frontmatter, favoriteProp, PropertyType.CHECKBOX);
|
||||
const creationDate: string | null = loadPropertyValue<string>(frontmatter, createdDateProp, PropertyType.DATE || PropertyType.DATETIME);
|
||||
const modifiedDate: string | null = loadPropertyValue<string>(frontmatter, modifiedDateProp, PropertyType.DATE || PropertyType.DATETIME);
|
||||
|
||||
const custom1: string | null = loadPropertyValue(frontmatter, custom1Prop);
|
||||
const custom2: string | null = loadPropertyValue(frontmatter, custom2Prop);
|
||||
const custom3: string | null = loadPropertyValue(frontmatter, custom3Prop);
|
||||
const custom1: string | null = loadPropertyValue<string>(frontmatter, custom1Prop, PropertyType.TEXT);
|
||||
const custom2: string | null = loadPropertyValue<string>(frontmatter, custom2Prop, PropertyType.TEXT);
|
||||
const custom3: string | null = loadPropertyValue<string>(frontmatter, custom3Prop, PropertyType.TEXT);
|
||||
|
||||
let createdMillis = file.stat.ctime;
|
||||
if (creationDate != null) {
|
||||
|
|
@ -62,29 +63,3 @@ export const formatFileDataForRender = (settings: VaultExplorerPluginSettings, f
|
|||
|
||||
};
|
||||
}
|
||||
|
||||
const loadPropertyValue = (frontmatter: FrontMatterCache | undefined, propertyName: string, isArray = false) => {
|
||||
if (propertyName === "") {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!frontmatter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const propertyValue = frontmatter?.[propertyName];
|
||||
|
||||
if (isArray) {
|
||||
if (propertyValue === undefined || propertyValue === null) {
|
||||
return null;
|
||||
} else if (Array.isArray(propertyValue)) {
|
||||
return propertyValue;
|
||||
} else {
|
||||
//If the property is not an array, return it as an array
|
||||
//This is a bug in Obsidian?
|
||||
return [propertyValue];
|
||||
}
|
||||
}
|
||||
|
||||
return propertyValue ?? null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ export interface MarkdownFileRenderData {
|
|||
name: string;
|
||||
path: string;
|
||||
tags: string[] | null;
|
||||
favorite: string | null;
|
||||
favorite: boolean | null;
|
||||
url: string | null;
|
||||
createdMillis: number;
|
||||
modifiedMillis: number;
|
||||
|
|
|
|||
235
src/svelte/shared/services/property-utils.test.ts
Normal file
235
src/svelte/shared/services/property-utils.test.ts
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
|
||||
import { FrontMatterCache } from "obsidian";
|
||||
import { PropertyType } from "src/types";
|
||||
import { loadPropertyValue } from "./property-utils";
|
||||
|
||||
describe("loadPropertyValue", () => {
|
||||
it("returns null if frontmatter is undefined", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache | undefined = undefined;
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, "test", PropertyType.TEXT);
|
||||
|
||||
//Assert
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null if propertyName is empty", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = {};
|
||||
const propertyName = "";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, propertyName, PropertyType.TEXT);
|
||||
|
||||
//Assert
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null if propertyValue is undefined", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = {};
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, propertyName, PropertyType.TEXT);
|
||||
|
||||
//Assert
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null if propertyValue is null", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: null };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, propertyName, PropertyType.TEXT);
|
||||
|
||||
//Assert
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null if expectedType is PropertyType.TEXT and value is not a string", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: 1 };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, propertyName, PropertyType.TEXT);
|
||||
|
||||
//Assert
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("returns propertyValue if expectedType is PropertyType.TEXT and value is a string", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: "test" };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, propertyName, PropertyType.TEXT);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe("test");
|
||||
});
|
||||
|
||||
it("returns null if expectedType is PropertyType.NUMBER and value is not a number", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { name: "test" };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<number>(frontmatter, propertyName, PropertyType.NUMBER);
|
||||
|
||||
//Assert
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("returns propertyValue if expectedType is PropertyType.NUMBER and value is a number", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: 1 };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<number>(frontmatter, propertyName, PropertyType.NUMBER);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(1);
|
||||
});
|
||||
|
||||
it("returns null if expectedType is PropertyType.CHECKBOX and value is not a boolean", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: "test" };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<boolean>(frontmatter, propertyName, PropertyType.CHECKBOX);
|
||||
|
||||
//Assert
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("returns propertyValue if expectedType is PropertyType.TEXT and value is a boolean", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: true };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<boolean>(frontmatter, propertyName, PropertyType.CHECKBOX);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("returns propertyValue as array if expectedType is PropertyType.LIST and value is an string", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: "test" };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string[]>(frontmatter, propertyName, PropertyType.LIST);
|
||||
|
||||
//Assert
|
||||
expect(result).toEqual(["test"]);
|
||||
});
|
||||
|
||||
it("returns propertyValue if expectedType is PropertyType.LIST and value is an array", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: ["test"] };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string[]>(frontmatter, propertyName, PropertyType.LIST);
|
||||
|
||||
//Assert
|
||||
expect(result).toEqual(["test"]);
|
||||
});
|
||||
|
||||
|
||||
it("returns propertyValue without null values if expectedType is PropertyType.LIST and value is an array", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: ["test", null] };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string[]>(frontmatter, propertyName, PropertyType.LIST);
|
||||
|
||||
//Assert
|
||||
expect(result).toEqual(["test"]);
|
||||
});
|
||||
|
||||
it("returns null if expectedType is PropertyType.DATE and value is not a string", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: 1 };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, propertyName, PropertyType.DATE);
|
||||
|
||||
//Assert
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null if expectedType is PropertyType.DATETIME and value is not a supported format", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: '<% tp.file.creation_date() %>' };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, propertyName, PropertyType.DATETIME);
|
||||
|
||||
//Assert
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
|
||||
it("returns propertyValue if expectedType is PropertyType.DATE and value is a string", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: "2021-01-01" };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, propertyName, PropertyType.DATE);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe("2021-01-01");
|
||||
});
|
||||
|
||||
it("returns null if expectedType is PropertyType.DATETIME and value is not a string", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: 1 };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, propertyName, PropertyType.DATETIME);
|
||||
|
||||
//Assert
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null if expectedType is PropertyType.DATETIME and value is not a supported format", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: '<% tp.file.last_modified_date("dddd Do MMMM YYYY HH: mm: ss") %>' };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, propertyName, PropertyType.DATETIME);
|
||||
|
||||
//Assert
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("returns propertyValue if expectedType is PropertyType.LIST and value is a string", () => {
|
||||
//Arrange
|
||||
const frontmatter: FrontMatterCache = { test: "2021-01-01T00:00:00" };
|
||||
const propertyName = "test";
|
||||
|
||||
//Act
|
||||
const result = loadPropertyValue<string>(frontmatter, propertyName, PropertyType.DATETIME);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe("2021-01-01T00:00:00");
|
||||
});
|
||||
});
|
||||
90
src/svelte/shared/services/property-utils.ts
Normal file
90
src/svelte/shared/services/property-utils.ts
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import Logger from "js-logger";
|
||||
import { FrontMatterCache } from "obsidian";
|
||||
import { PropertyType } from "src/types";
|
||||
import { isDateSupported } from "./time-utils";
|
||||
|
||||
/**
|
||||
* Loads a property value from the frontmatter object
|
||||
* @param frontmatter - The frontmatter object to load the property value from
|
||||
* @param propertyName - The name of the property to load
|
||||
* @param expectedType - The expected type of the property
|
||||
* @returns - The property value or null if the property isn't valid
|
||||
*/
|
||||
export const loadPropertyValue = <T>(frontmatter: FrontMatterCache | undefined, propertyName: string, expectedType: PropertyType): T | null => {
|
||||
//If the file has no frontmatter, return null
|
||||
if (!frontmatter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//If the property name is empty, return null
|
||||
//This can happen if the user has not set a property name
|
||||
if (propertyName === "") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const propertyValue = frontmatter[propertyName];
|
||||
|
||||
if (propertyValue === undefined || propertyValue === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Validate the property value for the expected type
|
||||
if (expectedType === PropertyType.TEXT) {
|
||||
if (typeof propertyValue !== "string") {
|
||||
Logger.warn(`Property value of type 'text' is not a string: ${propertyValue}`);
|
||||
return null;
|
||||
}
|
||||
} else if (expectedType === PropertyType.NUMBER) {
|
||||
if (typeof propertyValue !== "number") {
|
||||
Logger.warn(`Property value of type 'number' is not a number: ${propertyValue}`);
|
||||
return null;
|
||||
}
|
||||
} else if (expectedType === PropertyType.DATE) {
|
||||
if (typeof propertyValue !== "string") {
|
||||
Logger.warn(`Property value of type 'date' is not a string: ${propertyValue}`);
|
||||
return null;
|
||||
}
|
||||
} else if (expectedType === PropertyType.DATETIME) {
|
||||
if (typeof propertyValue !== "string") {
|
||||
Logger.warn(`Property value of type 'datetime' is not a string: ${propertyValue}`);
|
||||
return null;
|
||||
}
|
||||
} else if (expectedType === PropertyType.CHECKBOX) {
|
||||
if (typeof propertyValue !== "boolean") {
|
||||
Logger.warn(`Property value of type 'checkbox' is not a boolean: ${propertyValue}`);
|
||||
return null;
|
||||
}
|
||||
} else if (expectedType === PropertyType.LIST) {
|
||||
if (!Array.isArray(propertyValue)) {
|
||||
Logger.warn(`Property value of type 'list' is not an array: ${propertyValue}`);
|
||||
//Don't return null here, because the property value can be converted to an array
|
||||
}
|
||||
}
|
||||
|
||||
//In older versions of Obsidian, the date can be stored in the frontmatter
|
||||
//in a format other than YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS
|
||||
if (expectedType === PropertyType.DATE) {
|
||||
if (!isDateSupported(propertyValue)) {
|
||||
Logger.warn(`Property value of type 'date' has unsupported date format: ${propertyValue}`);
|
||||
return null;
|
||||
}
|
||||
} else if (expectedType === PropertyType.DATETIME) {
|
||||
if (!isDateSupported(propertyValue)) {
|
||||
Logger.warn(`Property value of type 'datetime' has unsupported date format: ${propertyValue}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (expectedType === PropertyType.LIST) {
|
||||
//If the property is not an array, return it as an array
|
||||
//This is a bug in Obsidian?
|
||||
if (!Array.isArray(propertyValue)) {
|
||||
return [propertyValue] as unknown as T;
|
||||
}
|
||||
|
||||
//Filter out null and undefined values
|
||||
return propertyValue.filter((v) => v !== null && v !== undefined) as unknown as T;
|
||||
}
|
||||
|
||||
return propertyValue as T;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["svelte", "node"],
|
||||
"types": ["svelte", "node", "jest"],
|
||||
"baseUrl": ".",
|
||||
"inlineSources": false,
|
||||
"module": "ESNext",
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
import { readFileSync, writeFileSync } from "fs";
|
||||
|
||||
const targetVersion = process.env.npm_package_version;
|
||||
|
||||
// read minAppVersion from manifest.json and bump version to target version
|
||||
let manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
|
||||
const { minAppVersion } = manifest;
|
||||
manifest.version = targetVersion;
|
||||
writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
|
||||
|
||||
// update versions.json with target version and minAppVersion from manifest.json
|
||||
let versions = JSON.parse(readFileSync("versions.json", "utf8"));
|
||||
versions[targetVersion] = minAppVersion;
|
||||
writeFileSync("versions.json", JSON.stringify(versions, null, "\t"));
|
||||
Loading…
Reference in a new issue