Skip to content

Commit e3b3818

Browse files
authored
refactor: improve consistency in variable names, comments, and docs (#56)
* docs: teach JSDoc about the @typeparam tag from TSDoc * test: provide mocks for obsidian-dataview types * style: consistent type-replacement name * style: sort members * docs: improvements and additions * style: keep comment next to code it's describing * refactor: split constants out into their own file * docs: fix broken type link
1 parent 4b37976 commit e3b3818

File tree

9 files changed

+72
-57
lines changed

9 files changed

+72
-57
lines changed

eslint.config.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,16 @@ export default defineConfig([
1616

1717
{ plugins: { js }, extends: ["js/recommended"] },
1818
{ plugins: { jsdoc }, files: ["**/*.{js,jsx}"], extends: ["jsdoc/flat/recommended-error"] },
19-
{ plugins: { jsdoc }, files: ["**/*.{ts,tsx}"], extends: ["jsdoc/flat/recommended-typescript-error"] },
19+
{
20+
plugins: { jsdoc },
21+
files: ["**/*.{ts,tsx}"],
22+
extends: ["jsdoc/flat/recommended-typescript-error"],
23+
settings: {
24+
// Define the core TSDoc tag [`@typeParam`](https://tsdoc.org/pages/tags/typeparam/)
25+
// See: https://github.com/gajus/eslint-plugin-jsdoc/issues/844#issuecomment-1051308663
26+
jsdoc: { structuredTags: { typeParam: { name: "namepath-defining", type: false } } },
27+
},
28+
},
2029
{ plugins: { tsdoc }, files: ["**/*.{ts,tsx}"], rules: { "tsdoc/syntax": "error" } },
2130

2231
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { vi } from "vitest";
2+
3+
export const getAPI = vi.fn();
4+
export const isPluginEnabled = vi.fn();

src/lib/obsidian-dataview/types.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import { DateTime } from "luxon";
2-
import { DataArray } from "obsidian-dataview/lib/api/data-array";
2+
import type { DataArray } from "obsidian-dataview/lib/api/data-array";
33
import type { DataviewApi as ActualDataviewApi } from "obsidian-dataview/lib/api/plugin-api";
44
import type { SMarkdownPage, STask } from "obsidian-dataview/lib/data-model/serialized/markdown";
5-
import type { Link as DataviewLink } from "obsidian-dataview/lib/data-model/value";
5+
import type { Link as ActualLink } from "obsidian-dataview/lib/data-model/value";
66

77
export { getAPI, isPluginEnabled } from "obsidian-dataview";
88

9-
/** The Obsidian 'link', used for uniquely describing a file, header, or block. Extended to improve type information. */
10-
export type Link = DataviewLink;
9+
/** The API that the obsidian-dataview plugin exposes to plugin authors. Extended to improve type information. */
10+
export declare class DataviewApi extends ActualDataviewApi {
11+
override pages(query: string): DataArray<SMarkdownPage>;
12+
}
1113

1214
/** The metadata that the obsidian-dataview plugin extracts from tasks. Extended to improve type information. */
1315
export interface DataviewMarkdownTask extends STask {
@@ -16,10 +18,8 @@ export interface DataviewMarkdownTask extends STask {
1618
completion?: DateTime;
1719
start?: DateTime;
1820
scheduled?: DateTime;
19-
section: Link;
21+
section: ActualLink;
2022
}
2123

22-
/** The API that the obsidian-dataview plugin exposes to plugin authors. Extended to improve type information. */
23-
export interface DataviewApi extends ActualDataviewApi {
24-
pages(query: string): DataArray<SMarkdownPage>;
25-
}
24+
/** The Obsidian 'link', used for uniquely describing a file, header, or block. Extended to improve type information. */
25+
export type Link = ActualLink;

src/model/collection/periodic-notes.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import { assertLuxonFormat, assertValid } from "@/util/luxon-utils";
88
import { DateBasedCollection } from "./schema";
99
import { sanitizeFolder } from "./util";
1010

11-
/** Configuration options for {@link PeriodicNotes}. */
11+
/**
12+
* Configuration options for {@link PeriodicNotes}.
13+
* @param IsValidConfiguration - whether the configuration is valid.
14+
*/
1215
export type PeriodicNotesConfig<IsValidConfiguration extends boolean> =
1316
IsValidConfiguration extends true ?
1417
{
@@ -37,16 +40,12 @@ export type PeriodicNotesConfig<IsValidConfiguration extends boolean> =
3740
};
3841

3942
/**
43+
* Intended to handle the popular "Periodic Notes" community plugin.
44+
* As a consequence, all files in the collection must be placed in the same folder.
4045
* @see {@link https://github.com/liamcain/obsidian-periodic-notes}
41-
*
42-
* A {@link DateBasedCollection} where each file corresponds to a unique {@link Interval} of time.
43-
* Intended to handle Obsidian's built-in "Daily Notes" plugin and the more-comprehensive "Periodic Notes" community
44-
* plugin. As a consequence, all files in the collection must be placed in the same folder.
45-
*
46-
* TODO: Is it worth supporting files organized into different folders?
4746
*/
4847
export class PeriodicNotes extends DateBasedCollection implements PeriodicNotesConfig<true> {
49-
/** The folder containing all of the notes. */
48+
/** The folder containing all of the notes. TODO: Support files organized into different folders. */
5049
public readonly folder: string;
5150

5251
/**
@@ -125,5 +124,6 @@ function validated(config: PeriodicNotesConfig<false>): PeriodicNotesConfig<true
125124
const indentedMessages = errors.map((error) => `${error.name}: ${error.message}`.replace(/^/gm, "\t"));
126125
throw new AggregateError(errors, ["invalid config", ...indentedMessages].join("\n"));
127126
}
127+
128128
return { folder, dateFormat, dateOptions, intervalDuration, intervalOffset };
129129
}

src/model/collection/schema.ts

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import { IntervalMaybeValid } from "luxon";
22

3-
/**
4-
* Interface for Bullet Journal collections.
5-
*
6-
* Provides efficient functions for common operations required by views and other models.
7-
*/
3+
/** Interface for Bullet Journal collections that provide efficient query functions. */
84
export abstract class Collection {
95
/**
106
* @param filePath - the path to check.
@@ -13,11 +9,11 @@ export abstract class Collection {
139
public abstract includes(filePath: string): boolean;
1410
}
1511

12+
/** A {@link Collection} where each note corresponds to a unique {@link luxon.Interval} of time. */
1613
export abstract class DateBasedCollection extends Collection {
1714
/**
18-
* Used to accurately enable date-based queries on collections and to look up "neighboring" files.
1915
* @param filePath - the path to check.
20-
* @returns the valid interval corresponding to the file, otherwise an invalid interval.
16+
* @returns the interval corresponding to the file, otherwise an invalid interval.
2117
*/
2218
public abstract getIntervalOf(filePath: string): IntervalMaybeValid;
2319

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { escapeRegExp, keysIn } from "lodash";
2+
import { PickByValue } from "utility-types";
3+
4+
import { Task } from "@/model/task/schema";
5+
import { PathsOf } from "@/util/type-utils";
6+
7+
export const SYMBOL_PATH_LOOKUP = {
8+
"❌": "dates.cancelled",
9+
"➕": "dates.created",
10+
"✅": "dates.done",
11+
"📅": "dates.due",
12+
"⌛": "dates.scheduled",
13+
"⏳": "dates.scheduled",
14+
"🛫": "dates.start",
15+
"⛔": "dependsOn",
16+
"🆔": "id",
17+
"🔺": "priority",
18+
"⏫": "priority",
19+
"🔼": "priority",
20+
"🔽": "priority",
21+
"⏬": "priority",
22+
} as const satisfies Record<string, PathsOf<Task>>;
23+
24+
export const SYMBOL_PRIORITY_LOOKUP = {
25+
"🔺": 0,
26+
"⏫": 1,
27+
"🔼": 2,
28+
"🔽": 4,
29+
"⏬": 5,
30+
} as const satisfies { [K in keyof PickByValue<typeof SYMBOL_PATH_LOOKUP, "priority">]: number };
31+
32+
export const SYMBOL_REG_EXP = new RegExp(keysIn(SYMBOL_PATH_LOOKUP).map(escapeRegExp).join("|"), "g");

src/model/task/lib/obsidian-tasks.ts

+4-30
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { escapeRegExp, has, keysIn, set } from "lodash";
1+
import { has, set } from "lodash";
22
import { DateTime } from "luxon";
3-
import { DeepPartial, PickByValue } from "utility-types";
3+
import { DeepPartial } from "utility-types";
44

55
import { Task } from "@/model/task/schema";
6-
import { PathsOf } from "@/util/type-utils";
6+
7+
import { SYMBOL_PATH_LOOKUP, SYMBOL_PRIORITY_LOOKUP, SYMBOL_REG_EXP } from "./obsidian-tasks.const";
78

89
/**
910
* Parses {@link Task} metadata from a real markdown blob using Obsidian Task's emoji format.
@@ -44,30 +45,3 @@ export function parseTaskEmojiFormat(text: string): DeepPartial<Task> {
4445

4546
return result;
4647
}
47-
48-
const SYMBOL_PATH_LOOKUP = {
49-
"❌": "dates.cancelled",
50-
"➕": "dates.created",
51-
"✅": "dates.done",
52-
"📅": "dates.due",
53-
"⌛": "dates.scheduled",
54-
"⏳": "dates.scheduled",
55-
"🛫": "dates.start",
56-
"⛔": "dependsOn",
57-
"🆔": "id",
58-
"🔺": "priority",
59-
"⏫": "priority",
60-
"🔼": "priority",
61-
"🔽": "priority",
62-
"⏬": "priority",
63-
} as const satisfies Record<string, PathsOf<Task>>;
64-
65-
const SYMBOL_PRIORITY_LOOKUP = {
66-
"🔺": 0,
67-
"⏫": 1,
68-
"🔼": 2,
69-
"🔽": 4,
70-
"⏬": 5,
71-
} as const satisfies { [K in keyof PickByValue<typeof SYMBOL_PATH_LOOKUP, "priority">]: number };
72-
73-
const SYMBOL_REG_EXP = new RegExp(keysIn(SYMBOL_PATH_LOOKUP).map(escapeRegExp).join("|"), "g");

src/util/luxon-utils.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ export function assertLuxonFormat(
3434
dateFormat: string,
3535
dateOptions?: DateTimeOptions,
3636
): asserts dateFormat is LuxonFormat {
37-
// NOTE: Any valid UTC date works.
38-
const sourceDate = DateTime.fromMillis(0).setZone("utc");
37+
const sourceDate = DateTime.fromMillis(0).setZone("utc"); // NOTE: Any valid UTC date works.
3938
const parsedDate = DateTime.fromFormat(sourceDate.toFormat(dateFormat, dateOptions), dateFormat, dateOptions);
4039
assert(
4140
parsedDate.isValid &&

src/util/type-utils.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/**
22
* The union of all dot-separated paths in an object rescursively.
3+
* @typeParam T - the object to get paths from.
34
* @example
45
*
56
* ```typescript

0 commit comments

Comments
 (0)