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

View File

@ -34,4 +34,9 @@ export default {
'TRY_AGAIN': 'Please try again', 'TRY_AGAIN': 'Please try again',
'POST_ID_ERROR': 'Published successfully but failed to get post ID', 'POST_ID_ERROR': 'Published successfully but failed to get post ID',
'SAVE_POST_ID_ERROR': 'Published successfully but failed to save 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': '请重试', 'TRY_AGAIN': '请重试',
'POST_ID_ERROR': '发布成功但无法获取帖子ID', 'POST_ID_ERROR': '发布成功但无法获取帖子ID',
'SAVE_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() { async loadSettings() {
@ -173,10 +182,10 @@ export default class DiscourseSyncPlugin extends Plugin {
if (response.status === 200) { if (response.status === 200) {
if (!isUpdate) { if (!isUpdate) {
try { try {
// Get new post ID // Get new post ID and topic ID
const responseData = response.json; const responseData = response.json;
if (responseData && responseData.id) { if (responseData && responseData.id) {
await this.updateFrontMatter(responseData.id); await this.updateFrontMatter(responseData.id, responseData.topic_id);
} else { } else {
return { return {
message: "Error", message: "Error",
@ -236,7 +245,7 @@ export default class DiscourseSyncPlugin extends Plugin {
} }
// Update frontmatter, add post ID // Update frontmatter, add post ID
private async updateFrontMatter(postId: number) { private async updateFrontMatter(postId: number, topicId: number) {
try { try {
// Get current active file // Get current active file
const activeFile = this.app.workspace.getActiveFile(); 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 content = await this.app.vault.read(activeFile);
const fm = this.getFrontMatter(content); const fm = this.getFrontMatter(content);
const discourseUrl = `${this.settings.baseUrl}/t/${topicId}`;
let newContent: string; let newContent: string;
if (fm) { if (fm) {
// Update existing frontmatter // 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`); newContent = content.replace(/^---\n[\s\S]*?\n---\n/, `---\n${yaml.stringify(updatedFm)}---\n`);
} else { } else {
// Add new frontmatter // 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}`; newContent = `---\n${yaml.stringify(newFm)}---\n${content}`;
} }
@ -393,6 +412,27 @@ export default class DiscourseSyncPlugin extends Plugin {
await this.openCategoryModal(); 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() {} onunload() {}
} }