@cueloop/integration-obsidian 0.1.0-alpha.33 → 0.1.0-alpha.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +21 -21
- package/src/detect.test.ts +3 -1
- package/src/detect.ts +10 -2
- package/src/export.test.ts +20 -4
- package/src/export.ts +5 -1
- package/src/filename.test.ts +6 -2
- package/src/filename.ts +6 -1
package/package.json
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cueloop/integration-obsidian",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.35",
|
|
4
|
+
"description": "Export reviewed cueloop plans into an Obsidian vault",
|
|
5
|
+
"homepage": "https://github.com/mmurakaru/cueloop#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/mmurakaru/cueloop/issues"
|
|
8
|
+
},
|
|
4
9
|
"license": "Apache-2.0",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/mmurakaru/cueloop.git",
|
|
13
|
+
"directory": "packages/integrations/obsidian"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"src",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
5
19
|
"type": "module",
|
|
6
20
|
"exports": {
|
|
7
21
|
".": "./src/index.ts"
|
|
8
22
|
},
|
|
9
|
-
"dependencies": {
|
|
10
|
-
"@cueloop/extension-api": "0.1.0-alpha.33",
|
|
11
|
-
"@cueloop/schema": "0.1.0-alpha.33"
|
|
12
|
-
},
|
|
13
23
|
"publishConfig": {
|
|
14
24
|
"access": "public"
|
|
15
25
|
},
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@cueloop/extension-api": "0.1.0-alpha.35",
|
|
28
|
+
"@cueloop/schema": "0.1.0-alpha.35"
|
|
29
|
+
},
|
|
20
30
|
"engines": {
|
|
21
31
|
"bun": ">=1.3.0"
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
"type": "git",
|
|
25
|
-
"url": "git+https://github.com/mmurakaru/cueloop.git",
|
|
26
|
-
"directory": "packages/integrations/obsidian"
|
|
27
|
-
},
|
|
28
|
-
"homepage": "https://github.com/mmurakaru/cueloop#readme",
|
|
29
|
-
"bugs": {
|
|
30
|
-
"url": "https://github.com/mmurakaru/cueloop/issues"
|
|
31
|
-
},
|
|
32
|
-
"description": "Export reviewed cueloop plans into an Obsidian vault"
|
|
33
|
-
}
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/detect.test.ts
CHANGED
|
@@ -47,7 +47,9 @@ describe("detectVaults", () => {
|
|
|
47
47
|
|
|
48
48
|
describe("obsidianConfigPath", () => {
|
|
49
49
|
test("resolves per platform", () => {
|
|
50
|
-
expect(obsidianConfigPath("darwin")).toContain(
|
|
50
|
+
expect(obsidianConfigPath("darwin")).toContain(
|
|
51
|
+
join("Library", "Application Support", "obsidian", "obsidian.json"),
|
|
52
|
+
);
|
|
51
53
|
expect(obsidianConfigPath("linux")).toContain(join("obsidian", "obsidian.json"));
|
|
52
54
|
expect(obsidianConfigPath("win32")).toContain(join("obsidian", "obsidian.json"));
|
|
53
55
|
});
|
package/src/detect.ts
CHANGED
|
@@ -14,9 +14,17 @@ export function obsidianConfigPath(platform: NodeJS.Platform = process.platform)
|
|
|
14
14
|
return join(homedir(), "Library", "Application Support", "obsidian", "obsidian.json");
|
|
15
15
|
}
|
|
16
16
|
if (platform === "win32") {
|
|
17
|
-
return join(
|
|
17
|
+
return join(
|
|
18
|
+
process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"),
|
|
19
|
+
"obsidian",
|
|
20
|
+
"obsidian.json",
|
|
21
|
+
);
|
|
18
22
|
}
|
|
19
|
-
return join(
|
|
23
|
+
return join(
|
|
24
|
+
process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"),
|
|
25
|
+
"obsidian",
|
|
26
|
+
"obsidian.json",
|
|
27
|
+
);
|
|
20
28
|
}
|
|
21
29
|
|
|
22
30
|
/** Vault paths registered with Obsidian that exist on disk. */
|
package/src/export.test.ts
CHANGED
|
@@ -20,7 +20,13 @@ function resolvedSession(overrides: Partial<ReviewSession> = {}): ReviewSession
|
|
|
20
20
|
content: "# Migration Plan\n\nMove the store.\n",
|
|
21
21
|
meta: { title: "Migration Plan" },
|
|
22
22
|
},
|
|
23
|
-
revisions: [
|
|
23
|
+
revisions: [
|
|
24
|
+
{
|
|
25
|
+
revision: 1,
|
|
26
|
+
content: "# Migration Plan\n\nMove the store.\n",
|
|
27
|
+
submittedAt: NOW.toISOString(),
|
|
28
|
+
},
|
|
29
|
+
],
|
|
24
30
|
annotations: [],
|
|
25
31
|
verdict: { kind: "approve", summary: "ship it", feedback: "", resolvedAt: NOW.toISOString() },
|
|
26
32
|
status: "resolved",
|
|
@@ -63,7 +69,9 @@ describe("exportSession", () => {
|
|
|
63
69
|
|
|
64
70
|
test("the working copy wins over the submitted content", () => {
|
|
65
71
|
// Arrange
|
|
66
|
-
const session = resolvedSession({
|
|
72
|
+
const session = resolvedSession({
|
|
73
|
+
workingCopy: "# Migration Plan\n\nMove the store carefully.\n",
|
|
74
|
+
});
|
|
67
75
|
|
|
68
76
|
// Act
|
|
69
77
|
const result = exportSession(session, config(), NOW);
|
|
@@ -92,7 +100,11 @@ describe("exportSession", () => {
|
|
|
92
100
|
const emptyConfigPath = join(vault, "obsidian.json");
|
|
93
101
|
|
|
94
102
|
// Act
|
|
95
|
-
const result = exportSession(
|
|
103
|
+
const result = exportSession(
|
|
104
|
+
resolvedSession(),
|
|
105
|
+
config({ vault: undefined, obsidianConfigPath: emptyConfigPath }),
|
|
106
|
+
NOW,
|
|
107
|
+
);
|
|
96
108
|
|
|
97
109
|
// Assert
|
|
98
110
|
expect(result.success).toBe(false);
|
|
@@ -116,7 +128,11 @@ describe("exportSession", () => {
|
|
|
116
128
|
writeFileSync(obsidianJson, JSON.stringify({ vaults: { v1: { path: detected } } }));
|
|
117
129
|
|
|
118
130
|
// Act
|
|
119
|
-
const result = exportSession(
|
|
131
|
+
const result = exportSession(
|
|
132
|
+
resolvedSession(),
|
|
133
|
+
config({ vault: undefined, obsidianConfigPath: obsidianJson }),
|
|
134
|
+
NOW,
|
|
135
|
+
);
|
|
120
136
|
|
|
121
137
|
// Assert
|
|
122
138
|
expect(result.success).toBe(true);
|
package/src/export.ts
CHANGED
|
@@ -43,7 +43,11 @@ export interface ExportResult {
|
|
|
43
43
|
error?: string;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export function exportSession(
|
|
46
|
+
export function exportSession(
|
|
47
|
+
session: ReviewSession,
|
|
48
|
+
config: ObsidianConfig,
|
|
49
|
+
now: Date = new Date(),
|
|
50
|
+
): ExportResult {
|
|
47
51
|
const vault = config.vault ?? detectVaults(config.obsidianConfigPath)[0];
|
|
48
52
|
if (!vault) return { success: false, error: "no Obsidian vault configured or detected" };
|
|
49
53
|
if (!existsSync(vault)) return { success: false, error: `vault not found: ${vault}` };
|
package/src/filename.test.ts
CHANGED
|
@@ -38,11 +38,15 @@ describe("titleFrom", () => {
|
|
|
38
38
|
|
|
39
39
|
describe("formatFilename", () => {
|
|
40
40
|
test("renders date tokens and the title with the space separator", () => {
|
|
41
|
-
expect(formatFilename("{YYYY}-{MM}-{DD} - {title}", "My Plan", DATE, "space")).toBe(
|
|
41
|
+
expect(formatFilename("{YYYY}-{MM}-{DD} - {title}", "My Plan", DATE, "space")).toBe(
|
|
42
|
+
"2026-08-07 - My Plan",
|
|
43
|
+
);
|
|
42
44
|
});
|
|
43
45
|
|
|
44
46
|
test("dash and underscore separators replace whitespace runs", () => {
|
|
45
|
-
expect(formatFilename("{YYYY}-{MM}-{DD} - {title}", "My Plan", DATE, "dash")).toBe(
|
|
47
|
+
expect(formatFilename("{YYYY}-{MM}-{DD} - {title}", "My Plan", DATE, "dash")).toBe(
|
|
48
|
+
"2026-08-07---My-Plan",
|
|
49
|
+
);
|
|
46
50
|
expect(formatFilename("{title}", "My Plan", DATE, "underscore")).toBe("My_Plan");
|
|
47
51
|
});
|
|
48
52
|
});
|
package/src/filename.ts
CHANGED
|
@@ -31,7 +31,12 @@ export function titleFrom(content: string, fallback?: string): string {
|
|
|
31
31
|
* Render the filename pattern ({YYYY}, {MM}, {DD}, {title}); each whitespace
|
|
32
32
|
* run in the result becomes the configured separator.
|
|
33
33
|
*/
|
|
34
|
-
export function formatFilename(
|
|
34
|
+
export function formatFilename(
|
|
35
|
+
format: string,
|
|
36
|
+
title: string,
|
|
37
|
+
date: Date,
|
|
38
|
+
separator: Separator = "space",
|
|
39
|
+
): string {
|
|
35
40
|
const pad = (value: number) => String(value).padStart(2, "0");
|
|
36
41
|
const name = format
|
|
37
42
|
.replaceAll("{YYYY}", String(date.getFullYear()))
|