Add "Open in Discourse" feature

- Implement command to open published Discourse post directly from Obsidian
- Update frontmatter to store topic ID and Discourse URL
- Add internationalization support for new feature
- Update README with new keyboard shortcut instructions
This commit is contained in:
wood chen 2025-02-16 16:51:19 +08:00
parent ac7efabc98
commit 29dd480242
4 changed files with 59 additions and 5 deletions

View File

@ -28,3 +28,7 @@
> 更新的前提是帖子本身是通过obsidian发布的.
![动图](./pics/20250124-001000.gif)
## 在discourse中打开
在笔记页面, 使用(Ctrl/Cmd + P)打开discourse的帖子.

View File

@ -34,4 +34,9 @@ export default {
'TRY_AGAIN': 'Please try again',
'POST_ID_ERROR': 'Published successfully but failed to get post ID',
'SAVE_POST_ID_ERROR': 'Published successfully but failed to save post ID',
// Open in Discourse
'OPEN_IN_DISCOURSE': 'Open in Discourse',
'NO_ACTIVE_FILE': 'No active file',
'NO_TOPIC_ID': 'This note has not been published to Discourse yet'
}

View File

@ -34,4 +34,9 @@ export default {
'TRY_AGAIN': '请重试',
'POST_ID_ERROR': '发布成功但无法获取帖子ID',
'SAVE_POST_ID_ERROR': '发布成功但无法保存帖子ID',
// Open in Discourse
'OPEN_IN_DISCOURSE': '在 Discourse 中打开',
'NO_ACTIVE_FILE': '没有打开的文件',
'NO_TOPIC_ID': '此笔记尚未发布到 Discourse'
}

View File

@ -37,6 +37,15 @@ export default class DiscourseSyncPlugin extends Plugin {
},
});
// Add command to open post in browser
this.addCommand({
id: "open-in-discourse",
name: t('OPEN_IN_DISCOURSE'),
callback: () => {
this.openInDiscourse();
},
});
}
async loadSettings() {
@ -173,10 +182,10 @@ export default class DiscourseSyncPlugin extends Plugin {
if (response.status === 200) {
if (!isUpdate) {
try {
// Get new post ID
// Get new post ID and topic ID
const responseData = response.json;
if (responseData && responseData.id) {
await this.updateFrontMatter(responseData.id);
await this.updateFrontMatter(responseData.id, responseData.topic_id);
} else {
return {
message: "Error",
@ -236,7 +245,7 @@ export default class DiscourseSyncPlugin extends Plugin {
}
// Update frontmatter, add post ID
private async updateFrontMatter(postId: number) {
private async updateFrontMatter(postId: number, topicId: number) {
try {
// Get current active file
const activeFile = this.app.workspace.getActiveFile();
@ -246,15 +255,25 @@ export default class DiscourseSyncPlugin extends Plugin {
const content = await this.app.vault.read(activeFile);
const fm = this.getFrontMatter(content);
const discourseUrl = `${this.settings.baseUrl}/t/${topicId}`;
let newContent: string;
if (fm) {
// Update existing frontmatter
const updatedFm = { ...fm, discourse_post_id: postId };
const updatedFm = {
...fm,
discourse_post_id: postId,
discourse_topic_id: topicId,
discourse_url: discourseUrl
};
newContent = content.replace(/^---\n[\s\S]*?\n---\n/, `---\n${yaml.stringify(updatedFm)}---\n`);
} else {
// Add new frontmatter
const newFm = { discourse_post_id: postId };
const newFm = {
discourse_post_id: postId,
discourse_topic_id: topicId,
discourse_url: discourseUrl
};
newContent = `---\n${yaml.stringify(newFm)}---\n${content}`;
}
@ -393,6 +412,27 @@ export default class DiscourseSyncPlugin extends Plugin {
await this.openCategoryModal();
}
private async openInDiscourse() {
const activeFile = this.app.workspace.getActiveFile();
if (!activeFile) {
new NotifyUser(this.app, t('NO_ACTIVE_FILE')).open();
return;
}
const content = await this.app.vault.read(activeFile);
const fm = this.getFrontMatter(content);
const discourseUrl = fm?.discourse_url;
const topicId = fm?.discourse_topic_id;
if (!discourseUrl && !topicId) {
new NotifyUser(this.app, t('NO_TOPIC_ID')).open();
return;
}
const url = discourseUrl || `${this.settings.baseUrl}/t/${topicId}`;
window.open(url, '_blank');
}
onunload() {}
}