obsidian-confluence 5.6.13 → 5.6.15

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/src/main.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { Plugin, Notice, MarkdownView, Workspace, loadMermaid } from "obsidian";
2
2
  import {
3
- ConfluenceUploadSettings,
4
- Publisher,
5
- ConfluencePageConfig,
6
- StaticSettingsLoader,
7
- renderADFDoc,
8
- MermaidRendererPlugin,
9
- UploadAdfFileResult,
3
+ ConfluenceUploadSettings,
4
+ Publisher,
5
+ ConfluencePageConfig,
6
+ StaticSettingsLoader,
7
+ renderADFDoc,
8
+ MermaidRendererPlugin,
9
+ UploadAdfFileResult,
10
10
  } from "md-confluence-lib";
11
11
  import { ElectronMermaidRenderer } from "md-confluence-mermaid-electron-renderer";
12
12
  import { ConfluenceSettingTab } from "./ConfluenceSettingTab";
@@ -14,488 +14,456 @@ import ObsidianAdaptor from "./adaptors/obsidian";
14
14
  import { CompletedModal } from "./CompletedModal";
15
15
  import { ObsidianConfluenceClient } from "./MyBaseClient";
16
16
  import {
17
- ConfluencePerPageForm,
18
- ConfluencePerPageUIValues,
19
- mapFrontmatterToConfluencePerPageUIValues,
17
+ ConfluencePerPageForm,
18
+ ConfluencePerPageUIValues,
19
+ mapFrontmatterToConfluencePerPageUIValues,
20
20
  } from "./ConfluencePerPageForm";
21
21
  import { Mermaid } from "mermaid";
22
22
 
23
23
  export interface ObsidianPluginSettings
24
- extends ConfluenceUploadSettings.ConfluenceSettings {
25
- mermaidTheme:
26
- | "match-obsidian"
27
- | "light-obsidian"
28
- | "dark-obsidian"
29
- | "default"
30
- | "neutral"
31
- | "dark"
32
- | "forest";
24
+ extends ConfluenceUploadSettings.ConfluenceSettings {
25
+ mermaidTheme:
26
+ | "match-obsidian"
27
+ | "light-obsidian"
28
+ | "dark-obsidian"
29
+ | "default"
30
+ | "neutral"
31
+ | "dark"
32
+ | "forest";
33
33
  }
34
34
 
35
35
  interface FailedFile {
36
- fileName: string;
37
- reason: string;
36
+ fileName: string;
37
+ reason: string;
38
38
  }
39
39
 
40
40
  interface UploadResults {
41
- errorMessage: string | null;
42
- failedFiles: FailedFile[];
43
- filesUploadResult: UploadAdfFileResult[];
41
+ errorMessage: string | null;
42
+ failedFiles: FailedFile[];
43
+ filesUploadResult: UploadAdfFileResult[];
44
44
  }
45
45
 
46
46
  export default class ConfluencePlugin extends Plugin {
47
- settings!: ObsidianPluginSettings;
48
- private isSyncing = false;
49
- workspace!: Workspace;
50
- publisher!: Publisher;
51
- adaptor!: ObsidianAdaptor;
52
-
53
- activeLeafPath(workspace: Workspace) {
54
- return workspace.getActiveViewOfType(MarkdownView)?.file.path;
55
- }
56
-
57
- async init() {
58
- await this.loadSettings();
59
- const { vault, metadataCache, workspace } = this.app;
60
- this.workspace = workspace;
61
- this.adaptor = new ObsidianAdaptor(
62
- vault,
63
- metadataCache,
64
- this.settings,
65
- this.app,
66
- );
67
-
68
- const mermaidItems = await this.getMermaidItems();
69
- const mermaidRenderer = new ElectronMermaidRenderer(
70
- mermaidItems.extraStyleSheets,
71
- mermaidItems.extraStyles,
72
- mermaidItems.mermaidConfig,
73
- mermaidItems.bodyStyles,
74
- );
75
- const confluenceClient = new ObsidianConfluenceClient({
76
- host: this.settings.confluenceBaseUrl,
77
- authentication: {
78
- basic: {
79
- email: this.settings.atlassianUserName,
80
- apiToken: this.settings.atlassianApiToken,
81
- },
82
- },
83
- middlewares: {
84
- onError(e) {
85
- if ("response" in e && "data" in e.response) {
86
- e.message =
87
- typeof e.response.data === "string"
88
- ? e.response.data
89
- : JSON.stringify(e.response.data);
90
- }
91
- },
92
- },
93
- });
94
-
95
- const settingsLoader = new StaticSettingsLoader(this.settings);
96
- this.publisher = new Publisher(
97
- this.adaptor,
98
- settingsLoader,
99
- confluenceClient,
100
- [new MermaidRendererPlugin(mermaidRenderer)],
101
- );
102
- }
103
-
104
- async getMermaidItems() {
105
- const extraStyles: string[] = [];
106
- const extraStyleSheets: string[] = [];
107
- let bodyStyles = "";
108
- const body = document.querySelector("body") as HTMLBodyElement;
109
-
110
- switch (this.settings.mermaidTheme) {
111
- case "default":
112
- case "neutral":
113
- case "dark":
114
- case "forest":
115
- return {
116
- extraStyleSheets,
117
- extraStyles,
118
- mermaidConfig: { theme: this.settings.mermaidTheme },
119
- bodyStyles,
120
- };
121
- case "match-obsidian":
122
- bodyStyles = body.className;
123
- break;
124
- case "dark-obsidian":
125
- bodyStyles = "theme-dark";
126
- break;
127
- case "light-obsidian":
128
- bodyStyles = "theme-dark";
129
- break;
130
- default:
131
- throw new Error("Missing theme");
132
- }
133
-
134
- extraStyleSheets.push("app://obsidian.md/app.css");
135
-
136
- // @ts-expect-error
137
- const cssTheme = this.app.vault?.getConfig("cssTheme") as string;
138
- if (cssTheme) {
139
- const fileExists = await this.app.vault.adapter.exists(
140
- `.obsidian/themes/${cssTheme}/theme.css`,
141
- );
142
- if (fileExists) {
143
- const themeCss = await this.app.vault.adapter.read(
144
- `.obsidian/themes/${cssTheme}/theme.css`,
145
- );
146
- extraStyles.push(themeCss);
147
- }
148
- }
149
-
150
- const cssSnippets =
151
- // @ts-expect-error
152
- (this.app.vault?.getConfig("enabledCssSnippets") as string[]) ?? [];
153
- for (const snippet of cssSnippets) {
154
- const fileExists = await this.app.vault.adapter.exists(
155
- `.obsidian/snippets/${snippet}.css`,
156
- );
157
- if (fileExists) {
158
- const themeCss = await this.app.vault.adapter.read(
159
- `.obsidian/snippets/${snippet}.css`,
160
- );
161
- extraStyles.push(themeCss);
162
- }
163
- }
164
-
165
- return {
166
- extraStyleSheets,
167
- extraStyles,
168
- mermaidConfig: (
169
- (await loadMermaid()) as Mermaid
170
- ).mermaidAPI.getConfig(),
171
- bodyStyles,
172
- };
173
- }
174
-
175
- async doPublish(publishFilter?: string): Promise<UploadResults> {
176
- const adrFiles = await this.publisher.publish(publishFilter);
177
-
178
- const returnVal: UploadResults = {
179
- errorMessage: null,
180
- failedFiles: [],
181
- filesUploadResult: [],
182
- };
183
-
184
- adrFiles.forEach((element) => {
185
- if (element.successfulUploadResult) {
186
- returnVal.filesUploadResult.push(
187
- element.successfulUploadResult,
188
- );
189
- return;
190
- }
191
-
192
- returnVal.failedFiles.push({
193
- fileName: element.node.file.absoluteFilePath,
194
- reason: element.reason ?? "No Reason Provided",
195
- });
196
- });
197
-
198
- return returnVal;
199
- }
200
-
201
- override async onload() {
202
- await this.init();
203
-
204
- this.addRibbonIcon("cloud", "Publish to Confluence", async () => {
205
- if (this.isSyncing) {
206
- new Notice("Syncing already on going");
207
- return;
208
- }
209
- this.isSyncing = true;
210
- try {
211
- const stats = await this.doPublish();
212
- new CompletedModal(this.app, {
213
- uploadResults: stats,
214
- }).open();
215
- } catch (error) {
216
- if (error instanceof Error) {
217
- new CompletedModal(this.app, {
218
- uploadResults: {
219
- errorMessage: error.message,
220
- failedFiles: [],
221
- filesUploadResult: [],
222
- },
223
- }).open();
224
- } else {
225
- new CompletedModal(this.app, {
226
- uploadResults: {
227
- errorMessage: JSON.stringify(error),
228
- failedFiles: [],
229
- filesUploadResult: [],
230
- },
231
- }).open();
232
- }
233
- } finally {
234
- this.isSyncing = false;
235
- }
236
- });
237
-
238
- this.addCommand({
239
- id: "adf-to-markdown",
240
- name: "ADF To Markdown",
241
- callback: async () => {
242
- console.log("HMMMM");
243
- const json = JSON.parse(
244
- '{"type":"doc","content":[{"type":"paragraph","content":[{"text":"Testing","type":"text"}]}],"version":1}',
245
- );
246
- console.log({ json });
247
-
248
- const confluenceClient = new ObsidianConfluenceClient({
249
- host: this.settings.confluenceBaseUrl,
250
- authentication: {
251
- basic: {
252
- email: this.settings.atlassianUserName,
253
- apiToken: this.settings.atlassianApiToken,
254
- },
255
- },
256
- });
257
- const testingPage =
258
- await confluenceClient.content.getContentById({
259
- id: "9732097",
260
- expand: ["body.atlas_doc_format", "space"],
261
- });
262
- const adf = JSON.parse(
263
- testingPage.body?.atlas_doc_format?.value ||
264
- '{type: "doc", content:[]}',
265
- );
266
- renderADFDoc(adf);
267
- },
268
- });
269
-
270
- this.addCommand({
271
- id: "publish-current",
272
- name: "Publish Current File to Confluence",
273
- checkCallback: (checking: boolean) => {
274
- if (!this.isSyncing) {
275
- if (!checking) {
276
- this.isSyncing = true;
277
- this.doPublish(this.activeLeafPath(this.workspace))
278
- .then((stats) => {
279
- new CompletedModal(this.app, {
280
- uploadResults: stats,
281
- }).open();
282
- })
283
- .catch((error) => {
284
- if (error instanceof Error) {
285
- new CompletedModal(this.app, {
286
- uploadResults: {
287
- errorMessage: error.message,
288
- failedFiles: [],
289
- filesUploadResult: [],
290
- },
291
- }).open();
292
- } else {
293
- new CompletedModal(this.app, {
294
- uploadResults: {
295
- errorMessage: JSON.stringify(error),
296
- failedFiles: [],
297
- filesUploadResult: [],
298
- },
299
- }).open();
300
- }
301
- })
302
- .finally(() => {
303
- this.isSyncing = false;
304
- });
305
- }
306
- return true;
307
- }
308
- return true;
309
- },
310
- });
311
-
312
- this.addCommand({
313
- id: "publish-all",
314
- name: "Publish All to Confluence",
315
- checkCallback: (checking: boolean) => {
316
- if (!this.isSyncing) {
317
- if (!checking) {
318
- this.isSyncing = true;
319
- this.doPublish()
320
- .then((stats) => {
321
- new CompletedModal(this.app, {
322
- uploadResults: stats,
323
- }).open();
324
- })
325
- .catch((error) => {
326
- if (error instanceof Error) {
327
- new CompletedModal(this.app, {
328
- uploadResults: {
329
- errorMessage: error.message,
330
- failedFiles: [],
331
- filesUploadResult: [],
332
- },
333
- }).open();
334
- } else {
335
- new CompletedModal(this.app, {
336
- uploadResults: {
337
- errorMessage: JSON.stringify(error),
338
- failedFiles: [],
339
- filesUploadResult: [],
340
- },
341
- }).open();
342
- }
343
- })
344
- .finally(() => {
345
- this.isSyncing = false;
346
- });
347
- }
348
- }
349
- return true;
350
- },
351
- });
352
-
353
- this.addCommand({
354
- id: "enable-publishing",
355
- name: "Enable publishing to Confluence",
356
- editorCheckCallback: (checking, _editor, view) => {
357
- if (!view.file) {
358
- return false;
359
- }
360
-
361
- if (checking) {
362
- const frontMatter = this.app.metadataCache.getCache(
363
- view.file.path,
364
- )?.frontmatter;
365
- const file = view.file;
366
- const enabledForPublishing =
367
- (file.path.startsWith(this.settings.folderToPublish) &&
368
- (!frontMatter ||
369
- frontMatter["connie-publish"] !== false)) ||
370
- (frontMatter && frontMatter["connie-publish"] === true);
371
- return !enabledForPublishing;
372
- }
373
-
374
- this.app.fileManager.processFrontMatter(
375
- view.file,
376
- (frontmatter) => {
377
- if (
378
- view.file &&
379
- view.file.path.startsWith(
380
- this.settings.folderToPublish,
381
- )
382
- ) {
383
- delete frontmatter["connie-publish"];
384
- } else {
385
- frontmatter["connie-publish"] = true;
386
- }
387
- },
388
- );
389
- return true;
390
- },
391
- });
392
-
393
- this.addCommand({
394
- id: "disable-publishing",
395
- name: "Disable publishing to Confluence",
396
- editorCheckCallback: (checking, _editor, view) => {
397
- if (!view.file) {
398
- return false;
399
- }
400
-
401
- if (checking) {
402
- const frontMatter = this.app.metadataCache.getCache(
403
- view.file.path,
404
- )?.frontmatter;
405
- const file = view.file;
406
- const enabledForPublishing =
407
- (file.path.startsWith(this.settings.folderToPublish) &&
408
- (!frontMatter ||
409
- frontMatter["connie-publish"] !== false)) ||
410
- (frontMatter && frontMatter["connie-publish"] === true);
411
- return enabledForPublishing;
412
- }
413
-
414
- this.app.fileManager.processFrontMatter(
415
- view.file,
416
- (frontmatter) => {
417
- if (
418
- view.file &&
419
- view.file.path.startsWith(
420
- this.settings.folderToPublish,
421
- )
422
- ) {
423
- frontmatter["connie-publish"] = false;
424
- } else {
425
- delete frontmatter["connie-publish"];
426
- }
427
- },
428
- );
429
- return true;
430
- },
431
- });
432
-
433
- this.addCommand({
434
- id: "page-settings",
435
- name: "Update Confluence Page Settings",
436
- editorCallback: (_editor, view) => {
437
- if (!view.file) {
438
- return false;
439
- }
440
-
441
- const frontMatter = this.app.metadataCache.getCache(
442
- view.file.path,
443
- )?.frontmatter;
444
-
445
- const file = view.file;
446
-
447
- new ConfluencePerPageForm(this.app, {
448
- config: ConfluencePageConfig.conniePerPageConfig,
449
- initialValues:
450
- mapFrontmatterToConfluencePerPageUIValues(frontMatter),
451
- onSubmit: (values, close) => {
452
- const valuesToSet: Partial<ConfluencePageConfig.ConfluencePerPageAllValues> =
453
- {};
454
- for (const propertyKey in values) {
455
- if (
456
- Object.prototype.hasOwnProperty.call(
457
- values,
458
- propertyKey,
459
- )
460
- ) {
461
- const element =
462
- values[
463
- propertyKey as keyof ConfluencePerPageUIValues
464
- ];
465
- if (element.isSet) {
466
- valuesToSet[
467
- propertyKey as keyof ConfluencePerPageUIValues
468
- ] = element.value as never;
469
- }
470
- }
471
- }
472
- this.adaptor.updateMarkdownValues(
473
- file.path,
474
- valuesToSet,
475
- );
476
- close();
477
- },
478
- }).open();
479
- return true;
480
- },
481
- });
482
-
483
- this.addSettingTab(new ConfluenceSettingTab(this.app, this));
484
- }
485
-
486
- override async onunload() {}
487
-
488
- async loadSettings() {
489
- this.settings = Object.assign(
490
- {},
491
- ConfluenceUploadSettings.DEFAULT_SETTINGS,
492
- { mermaidTheme: "match-obsidian" },
493
- await this.loadData(),
494
- );
495
- }
496
-
497
- async saveSettings() {
498
- await this.saveData(this.settings);
499
- await this.init();
500
- }
47
+ settings!: ObsidianPluginSettings;
48
+ private isSyncing = false;
49
+ workspace!: Workspace;
50
+ publisher!: Publisher;
51
+ adaptor!: ObsidianAdaptor;
52
+
53
+ activeLeafPath(workspace: Workspace) {
54
+ return workspace.getActiveViewOfType(MarkdownView)?.file.path;
55
+ }
56
+
57
+ async init() {
58
+ await this.loadSettings();
59
+ const { vault, metadataCache, workspace } = this.app;
60
+ this.workspace = workspace;
61
+ this.adaptor = new ObsidianAdaptor(
62
+ vault,
63
+ metadataCache,
64
+ this.settings,
65
+ this.app,
66
+ );
67
+
68
+ const mermaidItems = await this.getMermaidItems();
69
+ const mermaidRenderer = new ElectronMermaidRenderer(
70
+ mermaidItems.extraStyleSheets,
71
+ mermaidItems.extraStyles,
72
+ mermaidItems.mermaidConfig,
73
+ mermaidItems.bodyStyles,
74
+ );
75
+ const confluenceClient = new ObsidianConfluenceClient({
76
+ host: this.settings.confluenceBaseUrl,
77
+ authentication: {
78
+ basic: {
79
+ email: this.settings.atlassianUserName,
80
+ apiToken: this.settings.atlassianApiToken,
81
+ },
82
+ },
83
+ middlewares: {
84
+ onError(e) {
85
+ if ("response" in e && "data" in e.response) {
86
+ e.message =
87
+ typeof e.response.data === "string"
88
+ ? e.response.data
89
+ : JSON.stringify(e.response.data);
90
+ }
91
+ },
92
+ },
93
+ });
94
+
95
+ const settingsLoader = new StaticSettingsLoader(this.settings);
96
+ this.publisher = new Publisher(
97
+ this.adaptor,
98
+ settingsLoader,
99
+ confluenceClient,
100
+ [new MermaidRendererPlugin(mermaidRenderer)],
101
+ );
102
+ }
103
+
104
+ async getMermaidItems() {
105
+ const extraStyles: string[] = [];
106
+ const extraStyleSheets: string[] = [];
107
+ let bodyStyles = "";
108
+ const body = document.querySelector("body") as HTMLBodyElement;
109
+
110
+ switch (this.settings.mermaidTheme) {
111
+ case "default":
112
+ case "neutral":
113
+ case "dark":
114
+ case "forest":
115
+ return {
116
+ extraStyleSheets,
117
+ extraStyles,
118
+ mermaidConfig: { theme: this.settings.mermaidTheme },
119
+ bodyStyles,
120
+ };
121
+ case "match-obsidian":
122
+ bodyStyles = body.className;
123
+ break;
124
+ case "dark-obsidian":
125
+ bodyStyles = "theme-dark";
126
+ break;
127
+ case "light-obsidian":
128
+ bodyStyles = "theme-dark";
129
+ break;
130
+ default:
131
+ throw new Error("Missing theme");
132
+ }
133
+
134
+ extraStyleSheets.push("app://obsidian.md/app.css");
135
+
136
+ // @ts-expect-error
137
+ const cssTheme = this.app.vault?.getConfig("cssTheme") as string;
138
+ if (cssTheme) {
139
+ const fileExists = await this.app.vault.adapter.exists(
140
+ `.obsidian/themes/${cssTheme}/theme.css`,
141
+ );
142
+ if (fileExists) {
143
+ const themeCss = await this.app.vault.adapter.read(
144
+ `.obsidian/themes/${cssTheme}/theme.css`,
145
+ );
146
+ extraStyles.push(themeCss);
147
+ }
148
+ }
149
+
150
+ const cssSnippets =
151
+ // @ts-expect-error
152
+ (this.app.vault?.getConfig("enabledCssSnippets") as string[]) ?? [];
153
+ for (const snippet of cssSnippets) {
154
+ const fileExists = await this.app.vault.adapter.exists(
155
+ `.obsidian/snippets/${snippet}.css`,
156
+ );
157
+ if (fileExists) {
158
+ const themeCss = await this.app.vault.adapter.read(
159
+ `.obsidian/snippets/${snippet}.css`,
160
+ );
161
+ extraStyles.push(themeCss);
162
+ }
163
+ }
164
+
165
+ return {
166
+ extraStyleSheets,
167
+ extraStyles,
168
+ mermaidConfig: ((await loadMermaid()) as Mermaid).mermaidAPI.getConfig(),
169
+ bodyStyles,
170
+ };
171
+ }
172
+
173
+ async doPublish(publishFilter?: string): Promise<UploadResults> {
174
+ const adrFiles = await this.publisher.publish(publishFilter);
175
+
176
+ const returnVal: UploadResults = {
177
+ errorMessage: null,
178
+ failedFiles: [],
179
+ filesUploadResult: [],
180
+ };
181
+
182
+ adrFiles.forEach((element) => {
183
+ if (element.successfulUploadResult) {
184
+ returnVal.filesUploadResult.push(element.successfulUploadResult);
185
+ return;
186
+ }
187
+
188
+ returnVal.failedFiles.push({
189
+ fileName: element.node.file.absoluteFilePath,
190
+ reason: element.reason ?? "No Reason Provided",
191
+ });
192
+ });
193
+
194
+ return returnVal;
195
+ }
196
+
197
+ override async onload() {
198
+ await this.init();
199
+
200
+ this.addRibbonIcon("cloud", "Publish to Confluence", async () => {
201
+ if (this.isSyncing) {
202
+ new Notice("Syncing already on going");
203
+ return;
204
+ }
205
+ this.isSyncing = true;
206
+ try {
207
+ const stats = await this.doPublish();
208
+ new CompletedModal(this.app, {
209
+ uploadResults: stats,
210
+ }).open();
211
+ } catch (error) {
212
+ if (error instanceof Error) {
213
+ new CompletedModal(this.app, {
214
+ uploadResults: {
215
+ errorMessage: error.message,
216
+ failedFiles: [],
217
+ filesUploadResult: [],
218
+ },
219
+ }).open();
220
+ } else {
221
+ new CompletedModal(this.app, {
222
+ uploadResults: {
223
+ errorMessage: JSON.stringify(error),
224
+ failedFiles: [],
225
+ filesUploadResult: [],
226
+ },
227
+ }).open();
228
+ }
229
+ } finally {
230
+ this.isSyncing = false;
231
+ }
232
+ });
233
+
234
+ this.addCommand({
235
+ id: "adf-to-markdown",
236
+ name: "ADF To Markdown",
237
+ callback: async () => {
238
+ console.log("HMMMM");
239
+ const json = JSON.parse(
240
+ '{"type":"doc","content":[{"type":"paragraph","content":[{"text":"Testing","type":"text"}]}],"version":1}',
241
+ );
242
+ console.log({ json });
243
+
244
+ const confluenceClient = new ObsidianConfluenceClient({
245
+ host: this.settings.confluenceBaseUrl,
246
+ authentication: {
247
+ basic: {
248
+ email: this.settings.atlassianUserName,
249
+ apiToken: this.settings.atlassianApiToken,
250
+ },
251
+ },
252
+ });
253
+ const testingPage = await confluenceClient.content.getContentById({
254
+ id: "9732097",
255
+ expand: ["body.atlas_doc_format", "space"],
256
+ });
257
+ const adf = JSON.parse(
258
+ testingPage.body?.atlas_doc_format?.value ||
259
+ '{type: "doc", content:[]}',
260
+ );
261
+ renderADFDoc(adf);
262
+ },
263
+ });
264
+
265
+ this.addCommand({
266
+ id: "publish-current",
267
+ name: "Publish Current File to Confluence",
268
+ checkCallback: (checking: boolean) => {
269
+ if (!this.isSyncing) {
270
+ if (!checking) {
271
+ this.isSyncing = true;
272
+ this.doPublish(this.activeLeafPath(this.workspace))
273
+ .then((stats) => {
274
+ new CompletedModal(this.app, {
275
+ uploadResults: stats,
276
+ }).open();
277
+ })
278
+ .catch((error) => {
279
+ if (error instanceof Error) {
280
+ new CompletedModal(this.app, {
281
+ uploadResults: {
282
+ errorMessage: error.message,
283
+ failedFiles: [],
284
+ filesUploadResult: [],
285
+ },
286
+ }).open();
287
+ } else {
288
+ new CompletedModal(this.app, {
289
+ uploadResults: {
290
+ errorMessage: JSON.stringify(error),
291
+ failedFiles: [],
292
+ filesUploadResult: [],
293
+ },
294
+ }).open();
295
+ }
296
+ })
297
+ .finally(() => {
298
+ this.isSyncing = false;
299
+ });
300
+ }
301
+ return true;
302
+ }
303
+ return true;
304
+ },
305
+ });
306
+
307
+ this.addCommand({
308
+ id: "publish-all",
309
+ name: "Publish All to Confluence",
310
+ checkCallback: (checking: boolean) => {
311
+ if (!this.isSyncing) {
312
+ if (!checking) {
313
+ this.isSyncing = true;
314
+ this.doPublish()
315
+ .then((stats) => {
316
+ new CompletedModal(this.app, {
317
+ uploadResults: stats,
318
+ }).open();
319
+ })
320
+ .catch((error) => {
321
+ if (error instanceof Error) {
322
+ new CompletedModal(this.app, {
323
+ uploadResults: {
324
+ errorMessage: error.message,
325
+ failedFiles: [],
326
+ filesUploadResult: [],
327
+ },
328
+ }).open();
329
+ } else {
330
+ new CompletedModal(this.app, {
331
+ uploadResults: {
332
+ errorMessage: JSON.stringify(error),
333
+ failedFiles: [],
334
+ filesUploadResult: [],
335
+ },
336
+ }).open();
337
+ }
338
+ })
339
+ .finally(() => {
340
+ this.isSyncing = false;
341
+ });
342
+ }
343
+ }
344
+ return true;
345
+ },
346
+ });
347
+
348
+ this.addCommand({
349
+ id: "enable-publishing",
350
+ name: "Enable publishing to Confluence",
351
+ editorCheckCallback: (checking, _editor, view) => {
352
+ if (!view.file) {
353
+ return false;
354
+ }
355
+
356
+ if (checking) {
357
+ const frontMatter = this.app.metadataCache.getCache(view.file.path)
358
+ ?.frontmatter;
359
+ const file = view.file;
360
+ const enabledForPublishing =
361
+ (file.path.startsWith(this.settings.folderToPublish) &&
362
+ (!frontMatter || frontMatter["connie-publish"] !== false)) ||
363
+ (frontMatter && frontMatter["connie-publish"] === true);
364
+ return !enabledForPublishing;
365
+ }
366
+
367
+ this.app.fileManager.processFrontMatter(view.file, (frontmatter) => {
368
+ if (
369
+ view.file &&
370
+ view.file.path.startsWith(this.settings.folderToPublish)
371
+ ) {
372
+ delete frontmatter["connie-publish"];
373
+ } else {
374
+ frontmatter["connie-publish"] = true;
375
+ }
376
+ });
377
+ return true;
378
+ },
379
+ });
380
+
381
+ this.addCommand({
382
+ id: "disable-publishing",
383
+ name: "Disable publishing to Confluence",
384
+ editorCheckCallback: (checking, _editor, view) => {
385
+ if (!view.file) {
386
+ return false;
387
+ }
388
+
389
+ if (checking) {
390
+ const frontMatter = this.app.metadataCache.getCache(view.file.path)
391
+ ?.frontmatter;
392
+ const file = view.file;
393
+ const enabledForPublishing =
394
+ (file.path.startsWith(this.settings.folderToPublish) &&
395
+ (!frontMatter || frontMatter["connie-publish"] !== false)) ||
396
+ (frontMatter && frontMatter["connie-publish"] === true);
397
+ return enabledForPublishing;
398
+ }
399
+
400
+ this.app.fileManager.processFrontMatter(view.file, (frontmatter) => {
401
+ if (
402
+ view.file &&
403
+ view.file.path.startsWith(this.settings.folderToPublish)
404
+ ) {
405
+ frontmatter["connie-publish"] = false;
406
+ } else {
407
+ delete frontmatter["connie-publish"];
408
+ }
409
+ });
410
+ return true;
411
+ },
412
+ });
413
+
414
+ this.addCommand({
415
+ id: "page-settings",
416
+ name: "Update Confluence Page Settings",
417
+ editorCallback: (_editor, view) => {
418
+ if (!view.file) {
419
+ return false;
420
+ }
421
+
422
+ const frontMatter = this.app.metadataCache.getCache(view.file.path)
423
+ ?.frontmatter;
424
+
425
+ const file = view.file;
426
+
427
+ new ConfluencePerPageForm(this.app, {
428
+ config: ConfluencePageConfig.conniePerPageConfig,
429
+ initialValues: mapFrontmatterToConfluencePerPageUIValues(frontMatter),
430
+ onSubmit: (values, close) => {
431
+ const valuesToSet: Partial<ConfluencePageConfig.ConfluencePerPageAllValues> =
432
+ {};
433
+ for (const propertyKey in values) {
434
+ if (Object.prototype.hasOwnProperty.call(values, propertyKey)) {
435
+ const element =
436
+ values[propertyKey as keyof ConfluencePerPageUIValues];
437
+ if (element.isSet) {
438
+ valuesToSet[propertyKey as keyof ConfluencePerPageUIValues] =
439
+ element.value as never;
440
+ }
441
+ }
442
+ }
443
+ this.adaptor.updateMarkdownValues(file.path, valuesToSet);
444
+ close();
445
+ },
446
+ }).open();
447
+ return true;
448
+ },
449
+ });
450
+
451
+ this.addSettingTab(new ConfluenceSettingTab(this.app, this));
452
+ }
453
+
454
+ override async onunload() {}
455
+
456
+ async loadSettings() {
457
+ this.settings = Object.assign(
458
+ {},
459
+ ConfluenceUploadSettings.DEFAULT_SETTINGS,
460
+ { mermaidTheme: "match-obsidian" },
461
+ await this.loadData(),
462
+ );
463
+ }
464
+
465
+ async saveSettings() {
466
+ await this.saveData(this.settings);
467
+ await this.init();
468
+ }
501
469
  }