diff --git a/src/i18n.ts b/src/i18n.ts index d9ccf57..0e0413e 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -11,6 +11,7 @@ export type TranslationKey = | 'inline-code-copied' | 'block-id-copied' | 'note-link-copied' | 'heading-copied' | 'strikethrough-copied' | 'inline-latex-copied' | 'bold-copied' | 'highlight-copied' | 'italic-copied' | 'link-text-copied' | 'link-url-copied' | 'format' | 'add-to-menu' | 'add-to-menu-desc' | 'show-notice' | 'show-notice-desc' + | 'add-extra-commands' | 'add-extra-commands-desc' | 'use-heading-as-display' | 'use-heading-as-display-desc' | 'block-id' | 'use-frontmatter-as-display' | 'use-frontmatter-as-display-desc' | 'frontmatter-key' | 'frontmatter-key-desc' | 'link-format'| 'link-format-desc' | 'markdown-link' | 'wiki-link' | 'contextual-copy' @@ -26,6 +27,8 @@ export type TranslationKey = | 'auto-add-block-id' | 'auto-add-block-id-desc' | 'manual-block-id' | 'manual-block-id-desc' | 'modal-block-id' | 'modal-block-id-desc' + | 'auto-block-display-text' | 'auto-block-display-text-desc' + | 'generate-current-block-link-auto' | 'generate-current-block-link-manual' | 'error-block-id-empty' | 'error-block-id-invalid'; // 本地化翻译字典 @@ -66,6 +69,8 @@ export const translations: Record> = { 'target': 'Target', 'add-to-menu': 'Add to menu', 'add-to-menu-desc': 'Add the command to the context menu', + 'add-extra-commands': 'Add extra commands', + 'add-extra-commands-desc': 'Enable to add "Copy current note link" and "Generate & copy current block link" commands to the command palette', 'show-notice': 'Show notice', 'show-notice-desc': 'Show notification when content is copied', 'use-heading-as-display': 'Use heading as display text', @@ -90,10 +95,14 @@ export const translations: Record> = { 'enable-inline-latex-desc': 'Enable copying inline LaTeX like $latex example$', 'enable-link': 'Enable link title/url', 'enable-link-desc': 'Enable copying link like [linktitle](linkurl) - the plugin will copy the title or the URL of the link based on the current cursor position.', + 'auto-block-display-text': 'Auto display text for block links', + 'auto-block-display-text-desc': 'Automatically generate display text for block ID links (if disabled, block links will not show display text)', // 命令名称 'contextual-copy': 'Contextual copy', 'copy-current-file-link': 'Copy current file link', + 'generate-current-block-link-auto': 'Generate & copy current block link (auto)', + 'generate-current-block-link-manual': 'Generate & copy current block link (manual)', 'file-link-copied': 'File link copied!', }, [Language.ZH]: { @@ -127,6 +136,8 @@ export const translations: Record> = { 'target': '复制对象', 'add-to-menu': '添加到菜单', 'add-to-menu-desc': '将命令添加到右键菜单', + 'add-extra-commands': '添加拓展命令', + 'add-extra-commands-desc': '启用后,将在命令面板中添加“复制当前笔记的链接”和“生成并复制当前块的链接”命令', 'show-notice': '显示通知', 'show-notice-desc': '复制内容时显示通知提示', 'use-heading-as-display': '使用标题作为显示文本', @@ -155,16 +166,24 @@ export const translations: Record> = { // 命令名称 'contextual-copy': '智能复制', 'copy-current-file-link': '复制当前文件链接', + 'generate-current-block-link-auto': '生成并复制当前块链接(自动)', + 'generate-current-block-link-manual': '生成并复制当前块链接(手动)', 'file-link-copied': '当前文件链接已复制!', 'use-frontmatter-as-display': '使用 Frontmatter 属性作为显示文本', 'use-frontmatter-as-display-desc': '启用后,使用指定 Frontmatter 属性的值作为链接显示文本', 'frontmatter-key': 'Frontmatter 属性名', 'frontmatter-key-desc': '用于显示文本的 Frontmatter 属性名(默认:title)', + 'auto-block-display-text': '块链接自动显示文本', + 'auto-block-display-text-desc': '自动为块ID链接生成显示文本(关闭后,块链接不显示文本)', }, [Language.ZH_TW]: { // 复制 Block ID 'auto-add-block-id': '自動新增塊ID', 'auto-add-block-id-desc': '啟用後,若沒有可複製內容時,會自動在當前文本末尾新增一個隨機的塊ID(^xxxx)', + 'add-extra-commands': '添加擴展命令', + 'add-extra-commands-desc': '啟用後,會在命令面板中新增「複製當前筆記鏈接」和「生成並複製當前塊鏈接」命令', + 'auto-block-display-text': '塊連結自動顯示文本', + 'auto-block-display-text-desc': '自動為塊ID連結生成顯示文本(關閉後,塊連結不顯示文本)', 'manual-block-id': '手動輸入塊ID', 'manual-block-id-desc': '啟用後,可以在彈窗中手動輸入塊ID', 'modal-block-id': '輸入塊ID', @@ -221,6 +240,8 @@ export const translations: Record> = { // 命令名称 'contextual-copy': '智能複製', 'copy-current-file-link': '複製當前文件連結', + 'generate-current-block-link-auto': '生成並複製當前塊連結(自動)', + 'generate-current-block-link-manual': '生成並複製當前塊連結(手動)', 'file-link-copied': '當前文件連結已複製!', 'use-frontmatter-as-display': '使用屬性作為顯示文本', 'use-frontmatter-as-display-desc': '啟用後,使用指定屬性的值作為連結顯示文本', diff --git a/src/main.ts b/src/main.ts index 833c3d0..7bbd045 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,4 @@ -import { Editor, MarkdownView, Notice, Plugin, Menu, Platform } from 'obsidian'; +import { Editor, MarkdownView, Notice, Plugin, Menu, Platform, MarkdownFileInfo } from 'obsidian'; import { Language, TranslationKey, I18n } from './i18n'; import { ContextData, ContextType, DEFAULT_SETTINGS, EasyCopySettings, LinkFormat } from './type'; import { EasyCopySettingTab } from './settingTab'; @@ -34,14 +34,50 @@ export default class EasyCopy extends Plugin { } }); - // 新增:复制当前文件链接命令 - this.addCommand({ - id: 'copy-current-file-link', - name: this.t('copy-current-file-link'), - callback: () => { - this.copyCurrentFileLink(); - } - }); + if (this.settings.addExtraCommands){ + // 新增:复制当前文件链接命令 + this.addCommand({ + id: 'copy-current-file-link', + name: this.t('copy-current-file-link'), + callback: () => { + this.copyCurrentFileLink(); + } + }); + + // 新增:复制当前文件链接命令 + this.addCommand({ + id: 'generate-current-block-link-auto', + name: this.t('generate-current-block-link-auto'), + editorCallback: (editor: Editor, fileInfo: MarkdownFileInfo) => { + const file = fileInfo.file; + if (!file){ + new Notice(this.t('no-file')); + return; + } + const filename = file.basename; + // 自动生成名称 + this.insertBlockIdAndCopyLink(editor, filename, false); + } + }); + + // 新增:复制当前文件链接命令 + this.addCommand({ + id: 'generate-current-block-link-manual', + name: this.t('generate-current-block-link-manual'), + editorCallback: (editor: Editor, fileInfo: MarkdownFileInfo) => { + const file = fileInfo.file; + if (!file){ + new Notice(this.t('no-file')); + return; + } + const filename = file.basename; + // 手动输入名称 + this.insertBlockIdAndCopyLink(editor, filename, true); + } + }); + + } + // This adds a settings tab so the user can configure various aspects of the plugin this.addSettingTab(new EasyCopySettingTab(this.app, this)); @@ -304,54 +340,11 @@ export default class EasyCopy extends Plugin { if (contextType.type == ContextType.NULL) { // 如果启用自动添加 Block ID if (this.settings.autoAddBlockId) { - let blockId = ''; const isManual = this.settings.allowManualBlockId; + + await this.insertBlockIdAndCopyLink(editor, filename, isManual); + - if (isManual) { - // 用 Modal 弹窗获取 Block ID - const modalBlockId = await new Promise((resolve) => { - new BlockIdInputModal(this.app, - this.t('modal-block-id'), this.t('modal-block-id-desc'), - this.t.bind(this), - (result: any) => { - resolve(result ?? null); - } - ).open(); - }); - if (!modalBlockId) return; - blockId = modalBlockId; - } else { - // 随机生成 - const randomId = Math.random().toString(36).substr(2, 6); - blockId = `${randomId}`; - } - - // —— 新逻辑:定位 block(段落)末尾 —— - const cursor = editor.getCursor(); - const { start, end } = this.detectBlockRange(editor, cursor.line); - const firstLine = editor.getLine(start); - const lastLine = editor.getLine(end); - - // 检查 block 最后一行末是否已有块ID - if (!/\^[a-zA-Z0-9_-]+$/.test(lastLine.trim())) { - // 在 block 最后一行末尾插入块ID - let insertText = '^'+blockId; - - if (lastLine.startsWith('> ') || lastLine.startsWith('``')) { - insertText = '\n' + insertText; - } else if (!lastLine.endsWith(' ')) { - insertText = ' ' + insertText; - } - - editor.replaceRange(insertText, { line: end, ch: lastLine.length }); - - // 如果不是手动输入的,使用简短的显示文本 - const useBrief = !isManual; - - // 复制块ID链接 - this.copyBlockLink(blockId, filename, useBrief, firstLine); - return; - } } new Notice(this.t('no-content')); @@ -425,9 +418,12 @@ export default class EasyCopy extends Plugin { /* * 复制块链接 */ - private copyBlockLink(content: string, filename: string, useBrief: boolean, firstLine: string=''): void { + private copyBlockLink(content: string, filename: string, useBrief: boolean, firstLine=''): void { const blockId = content; + let text = firstLine; + + const autoDisplayText = this.settings.autoBlockDisplayText; // 先去掉结尾的 ^ 及其后面的内容(如果有的话) text = text.replace(/\^.*\s*$/, ''); @@ -465,15 +461,22 @@ export default class EasyCopy extends Plugin { } else { displayText = tempText; } + } else { + displayText = briefText; } } } // displayText = "^"+displayText; + let blockIdLink = this.settings.linkFormat === LinkFormat.WIKILINK + ? `[[${filename}#^${blockId}|${displayText}]]` + : `[^${displayText}](${filename}#^${blockId})`; - const blockIdLink = this.settings.linkFormat === LinkFormat.WIKILINK - ? `[[${filename}#^${blockId}|${displayText}]]` - : `[^${displayText}](${filename}#^${blockId})`; + if (!autoDisplayText) { + blockIdLink = this.settings.linkFormat === LinkFormat.WIKILINK + ? `[[${filename}#^${blockId}]]` + : `[](${filename}#^${blockId})`; + } navigator.clipboard.writeText(blockIdLink); if (this.settings.showNotice) { @@ -564,6 +567,60 @@ export default class EasyCopy extends Plugin { } } + /** + * 插入 Block ID 并复制块链接 + * @param editor 编辑器实例 + * @param filename 当前文件名 + */ + private async insertBlockIdAndCopyLink(editor: Editor, filename: string, isManual=false): Promise { + let blockId = ''; + + if (isManual) { + // 用 Modal 弹窗获取 Block ID + const modalBlockId = await new Promise((resolve) => { + new BlockIdInputModal(this.app, + this.t('modal-block-id'), this.t('modal-block-id-desc'), + this.t.bind(this), + (result: any) => { + resolve(result ?? null); + } + ).open(); + }); + if (!modalBlockId) return; + blockId = modalBlockId; + } else { + // 随机生成 + const randomId = Math.random().toString(36).substr(2, 6); + blockId = `${randomId}`; + } + + // —— 新逻辑:定位 block(段落)末尾 —— + const cursor = editor.getCursor(); + const { start, end } = this.detectBlockRange(editor, cursor.line); + const firstLine = editor.getLine(start); + const lastLine = editor.getLine(end); + + // 检查 block 最后一行末是否已有块ID + if (!/\^[a-zA-Z0-9_-]+$/.test(lastLine.trim())) { + // 在 block 最后一行末尾插入块ID + let insertText = '^' + blockId; + + if (lastLine.startsWith('> ') || lastLine.startsWith('``')) { + insertText = '\n' + insertText; + } else if (!lastLine.endsWith(' ')) { + insertText = ' ' + insertText; + } + + editor.replaceRange(insertText, { line: end, ch: lastLine.length }); + + // 如果不是手动输入的,使用简短的显示文本 + const useBrief = !isManual; + + // (生成之后)复制块ID链接 + this.copyBlockLink(blockId, filename, useBrief, firstLine); + } + } + /** * 初始化国际化设置,使用Obsidian的语言设置 */ diff --git a/src/settingTab.ts b/src/settingTab.ts index c418572..42a1897 100644 --- a/src/settingTab.ts +++ b/src/settingTab.ts @@ -26,6 +26,16 @@ export class EasyCopySettingTab extends PluginSettingTab { await this.plugin.saveSettings(); })); + new Setting(containerEl) + .setName(this.plugin.t('add-extra-commands')) + .setDesc(this.plugin.t('add-extra-commands-desc')) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.addExtraCommands) + .onChange(async (value) => { + this.plugin.settings.addExtraCommands = value; + await this.plugin.saveSettings(); + })); + new Setting(containerEl) .setName(this.plugin.t('show-notice')) .setDesc(this.plugin.t('show-notice-desc')) @@ -68,6 +78,20 @@ export class EasyCopySettingTab extends PluginSettingTab { ); } + + // 新增:自动为 Block 链接添加显示文本 + new Setting(containerEl) + .setName(this.plugin.t('auto-block-display-text')) + .setDesc(this.plugin.t('auto-block-display-text-desc')) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.autoBlockDisplayText) + .onChange(async (value) => { + this.plugin.settings.autoBlockDisplayText = value; + await this.plugin.saveSettings(); + this.display(); + }) + ); + new Setting(containerEl) .setName(this.plugin.t('use-heading-as-display')) .setDesc(this.plugin.t('use-heading-as-display-desc')) diff --git a/src/type.ts b/src/type.ts index 0781bd5..4476d7b 100644 --- a/src/type.ts +++ b/src/type.ts @@ -28,6 +28,7 @@ export interface EasyCopySettings { useFrontmatterAsDisplay: boolean; // 是否使用 frontmatter 属性作为显示文本 frontmatterKey: string; // frontmatter 属性名 addToMenu: boolean; + addExtraCommands: boolean; showNotice: boolean; useHeadingAsDisplayText: boolean; linkFormat: LinkFormat; @@ -41,12 +42,14 @@ export interface EasyCopySettings { enableLink: boolean; autoAddBlockId: boolean; // 是否自动添加 Block ID allowManualBlockId: boolean; // 是否允许手动输入 Block ID + autoBlockDisplayText: boolean; // 自动为 Block 添加显示文本 } export const DEFAULT_SETTINGS: EasyCopySettings = { useFrontmatterAsDisplay: false, frontmatterKey: 'title', addToMenu: true, + addExtraCommands: true, showNotice: true, useHeadingAsDisplayText: true, linkFormat: LinkFormat.WIKILINK, @@ -60,4 +63,5 @@ export const DEFAULT_SETTINGS: EasyCopySettings = { enableLink: true, autoAddBlockId: false, // 默认关闭 allowManualBlockId: false, // 默认关闭 + autoBlockDisplayText: true, } \ No newline at end of file