b72f36926a
- 添加文章搜索命令,支持按关键词筛选和发布状态过滤 - 新增文章导出功能,支持导出为 Markdown 和 JSON 格式 - 扩展国际化配置,添加相关翻译文本 - 更新功能增强计划文档,标记已完成功能 - 移除不再需要的下载信息和插件清单文件
236 lines
7.2 KiB
TypeScript
236 lines
7.2 KiB
TypeScript
import i18next from "i18next";
|
|
import { Notice, Plugin, moment } from "obsidian";
|
|
import { resources } from "./i18n";
|
|
import { addHaloIcon } from "./icons";
|
|
import { openPostSelectionModal } from "./post-selection-model";
|
|
import { importFromMarkdownFile } from "./commands/import-markdown";
|
|
import { deletePost } from "./commands/delete-post";
|
|
import { manageTags, manageCategories } from "./commands/manage-taxonomy";
|
|
import { exportPostAsMarkdown, exportPostAsJson } from "./commands/export-post";
|
|
import { searchPosts } from "./commands/search-posts";
|
|
import { DEFAULT_SETTINGS, type HaloSetting, HaloSettingTab, type HaloSite } from "./settings";
|
|
import HaloService from "./service";
|
|
import { openSiteSelectionModal } from "./site-selection-modal";
|
|
|
|
export default class HaloPlugin extends Plugin {
|
|
settings: HaloSetting;
|
|
|
|
async onload() {
|
|
console.log("loading obsidian-halo plugin");
|
|
|
|
await i18next.init({
|
|
lng: moment.locale(),
|
|
fallbackLng: "en",
|
|
resources,
|
|
returnNull: false,
|
|
});
|
|
|
|
await this.loadSettings();
|
|
|
|
addHaloIcon();
|
|
|
|
this.addRibbonIcon("halo-logo", i18next.t("ribbon_icon.publish"), async (evt: MouseEvent) => {
|
|
await this.publishCommand();
|
|
});
|
|
|
|
this.addCommand({
|
|
id: "publish",
|
|
name: i18next.t("command.publish.name"),
|
|
callback: async () => {
|
|
await this.publishCommand();
|
|
},
|
|
});
|
|
|
|
this.addCommand({
|
|
id: "publish-with-defaults",
|
|
name: i18next.t("command.publish_with_defaults.name"),
|
|
callback: async () => {
|
|
const site = this.settings.sites.find((site) => site.default);
|
|
|
|
if (!site) {
|
|
new Notice(i18next.t("command.publish_with_defaults.error_no_default_site"));
|
|
return;
|
|
}
|
|
|
|
const service = new HaloService(this.app, this.settings, site);
|
|
await service.publishPost();
|
|
},
|
|
});
|
|
|
|
this.addCommand({
|
|
id: "update-post",
|
|
name: i18next.t("command.update_post.name"),
|
|
editorCallback: async () => {
|
|
const { activeEditor } = this.app.workspace;
|
|
|
|
if (!activeEditor || !activeEditor.file) {
|
|
return;
|
|
}
|
|
|
|
const matterData = this.app.metadataCache.getFileCache(activeEditor.file)?.frontmatter;
|
|
|
|
if (!matterData?.halo?.site) {
|
|
new Notice(i18next.t("command.update_post.error_not_published"));
|
|
return;
|
|
}
|
|
|
|
const site = this.settings.sites.find((site) => site.url === matterData.halo?.site);
|
|
|
|
if (!site) {
|
|
new Notice(i18next.t("command.update_post.error_no_matched_site"));
|
|
return;
|
|
}
|
|
|
|
const service = new HaloService(this.app, this.settings, site);
|
|
|
|
await service.updatePost();
|
|
|
|
new Notice(i18next.t("command.update_post.success"));
|
|
},
|
|
});
|
|
|
|
this.addCommand({
|
|
id: "pull-post",
|
|
name: i18next.t("command.pull_post.name"),
|
|
callback: async () => {
|
|
if (this.settings.sites.length === 0) {
|
|
new Notice(i18next.t("command.pull_post.error_no_sites"));
|
|
return;
|
|
}
|
|
|
|
let site: HaloSite = this.settings.sites[0];
|
|
|
|
if (this.settings.sites.length > 1) {
|
|
site = await openSiteSelectionModal(this);
|
|
}
|
|
|
|
const post = await openPostSelectionModal(this, site);
|
|
|
|
const service = new HaloService(this.app, this.settings, site);
|
|
await service.pullPost(post.post.metadata.name);
|
|
},
|
|
});
|
|
|
|
this.addCommand({
|
|
id: "import-markdown",
|
|
name: i18next.t("command.import_markdown.name"),
|
|
callback: async () => {
|
|
await importFromMarkdownFile(this);
|
|
},
|
|
});
|
|
|
|
this.addCommand({
|
|
id: "delete-post",
|
|
name: i18next.t("command.delete_post.name"),
|
|
editorCallback: async () => {
|
|
await deletePost(this);
|
|
},
|
|
});
|
|
|
|
this.addCommand({
|
|
id: "manage-tags",
|
|
name: i18next.t("command.manage_tags.name"),
|
|
callback: async () => {
|
|
await manageTags(this);
|
|
},
|
|
});
|
|
|
|
this.addCommand({
|
|
id: "manage-categories",
|
|
name: i18next.t("command.manage_categories.name"),
|
|
callback: async () => {
|
|
await manageCategories(this);
|
|
},
|
|
});
|
|
|
|
this.addCommand({
|
|
id: "search-posts",
|
|
name: i18next.t("command.search_posts.name"),
|
|
callback: async () => {
|
|
await searchPosts(this);
|
|
},
|
|
});
|
|
|
|
this.addCommand({
|
|
id: "export-post-as-markdown",
|
|
name: i18next.t("command.export_markdown.name"),
|
|
editorCallback: async () => {
|
|
const { activeEditor } = this.app.workspace;
|
|
if (!activeEditor || !activeEditor.file) return;
|
|
const matterData = this.app.metadataCache.getFileCache(activeEditor.file)?.frontmatter;
|
|
if (!matterData?.halo?.name) {
|
|
new Notice(i18next.t("command.export_markdown.error_not_published"));
|
|
return;
|
|
}
|
|
await exportPostAsMarkdown(this, matterData.halo.name, matterData.title || activeEditor.file.basename);
|
|
},
|
|
});
|
|
|
|
this.addCommand({
|
|
id: "export-post-as-json",
|
|
name: i18next.t("command.export_json.name"),
|
|
editorCallback: async () => {
|
|
const { activeEditor } = this.app.workspace;
|
|
if (!activeEditor || !activeEditor.file) return;
|
|
const matterData = this.app.metadataCache.getFileCache(activeEditor.file)?.frontmatter;
|
|
if (!matterData?.halo?.name) {
|
|
new Notice(i18next.t("command.export_json.error_not_published"));
|
|
return;
|
|
}
|
|
await exportPostAsJson(this, matterData.halo.name, matterData.title || activeEditor.file.basename);
|
|
},
|
|
});
|
|
|
|
this.addSettingTab(new HaloSettingTab(this));
|
|
}
|
|
|
|
onunload() {}
|
|
|
|
async loadSettings() {
|
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
|
}
|
|
|
|
async saveSettings() {
|
|
await this.saveData(this.settings);
|
|
}
|
|
|
|
private async publishCommand() {
|
|
console.log("[HaloPlugin] 执行发布命令");
|
|
|
|
const { activeEditor } = this.app.workspace;
|
|
console.log(`[HaloPlugin] activeEditor: ${activeEditor ? '存在' : '不存在'}`);
|
|
|
|
if (!activeEditor || !activeEditor.file) {
|
|
console.log("[HaloPlugin] 没有打开的编辑器,退出");
|
|
return;
|
|
}
|
|
|
|
console.log(`[HaloPlugin] 当前文件: ${activeEditor.file.path}`);
|
|
|
|
const matterData = this.app.metadataCache.getFileCache(activeEditor.file)?.frontmatter;
|
|
console.log(`[HaloPlugin] frontmatter: ${JSON.stringify(matterData)}`);
|
|
|
|
if (matterData?.halo?.site) {
|
|
console.log(`[HaloPlugin] 检测到已发布的文章,站点: ${matterData.halo.site}`);
|
|
const site = this.settings.sites.find((site) => site.url === matterData.halo.site);
|
|
|
|
if (!site) {
|
|
console.log("[HaloPlugin] 未找到匹配的站点配置");
|
|
new Notice(i18next.t("command.publish.error_no_matched_site"));
|
|
return;
|
|
}
|
|
|
|
console.log(`[HaloPlugin] 找到站点: ${site.name}, URL: ${site.url}`);
|
|
const service = new HaloService(this.app, this.settings, site);
|
|
await service.publishPost();
|
|
return;
|
|
}
|
|
|
|
console.log("[HaloPlugin] 文章未发布过,需要选择站点");
|
|
const site = await openSiteSelectionModal(this);
|
|
console.log(`[HaloPlugin] 选择站点: ${site.name}, URL: ${site.url}`);
|
|
const service = new HaloService(this.app, this.settings, site);
|
|
await service.publishPost();
|
|
}
|
|
}
|