From 28b11fdc91b36379e2be750348628f18cfcfd6ce Mon Sep 17 00:00:00 2001 From: William Nurmi Date: Fri, 12 Jun 2026 12:23:01 +0300 Subject: [PATCH] feat: gate full-block display text behind a default-off setting The previous commit changed the display-text source for block links from a single line to the whole multi-line block for everyone. Make the new behavior opt-in instead: - new setting "Use the whole block as display text" (blockDisplayFullBlock, default off). With the toggle off the display-text source is exactly the pre-existing single-line one: the detected block-id line when copying an existing id, the first line of the block when inserting a new id. - with the toggle on, tables, code blocks and math blocks fall back to the block id as display text instead of joining their markup into the alias (matching the old fallback for standalone-id forms). - strip | from the display text unconditionally: a pipe inside [[link|alias]] truncates the alias, and breaks the table row when the link is pasted into a table. This also affected the old single-line behavior when copying from table rows. Settings UI and i18n strings (EN/ZH/ZH-TW) included. --- src/i18n.ts | 9 ++++++++- src/linkBuilder.test.ts | 7 +++++++ src/linkBuilder.ts | 3 ++- src/main.ts | 26 ++++++++++++++++++++------ src/settingTab.ts | 11 +++++++++++ src/type.ts | 2 ++ 6 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/i18n.ts b/src/i18n.ts index d6208a3..1111e02 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -42,7 +42,8 @@ export type TranslationKey = | 'block-id-insert-position' | 'block-id-insert-position-desc' | 'block-id-end-of-block' | 'block-id-next-line' | 'block-id-next-line-with-gap' | 'modal-block-id' | 'modal-block-id-desc' - | 'auto-block-display-text' | 'auto-block-display-text-desc' + | 'auto-block-display-text' | 'auto-block-display-text-desc' + | 'block-display-full-block' | 'block-display-full-block-desc' | 'block-display-word-limit' | 'block-display-word-limit-desc' | 'block-display-char-limit' | 'block-display-char-limit-desc' | 'generate-current-block-link-auto' | 'generate-current-block-link-manual' @@ -136,6 +137,8 @@ export const translations: Record> = { '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': 'Generate display text for block links', 'auto-block-display-text-desc': 'If enabled, display text will be automatically added to generated block ID links', + 'block-display-full-block': 'Use the whole block as display text', + 'block-display-full-block-desc': 'If enabled, the display text is taken from the whole (multi-line) block: soft-wrapped continuation lines are joined with spaces. If disabled, only a single line is used (legacy behavior). Tables, code blocks and math blocks fall back to the block ID.', 'block-display-word-limit': 'Block Display Text: Word limit for English-like languages', 'block-display-word-limit-desc': 'Maximum number of words to show in block display text for space-separated languages (e.g., English "this is a sentence")', 'block-display-char-limit': 'Block Display Text: Character limit for CJK-like languages', @@ -280,6 +283,8 @@ export const translations: Record> = { 'frontmatter-key-desc': '用于显示文本的笔记属性名(默认:title)', 'auto-block-display-text': '生成块链接的显示文本', 'auto-block-display-text-desc': '启用后,会自动为生成的块ID链接添加显示文本', + 'block-display-full-block': '显示文本取整个块', + 'block-display-full-block-desc': '启用后,显示文本取自整个(多行)块:软换行的后续行会用空格拼接。关闭时仅使用单独一行(旧版行为)。表格、代码块和数学块会回退到块 ID。', 'block-display-word-limit': '块显示文本:英语类语言的单词数限制', 'block-display-word-limit-desc': '使用空格分隔的语言(如英语 "this is a sentence")在块显示文本中显示的最大单词数', 'block-display-char-limit': '块显示文本:CJK 类语言的字符数限制', @@ -299,6 +304,8 @@ export const translations: Record> = { 'add-extra-commands-desc': '啟用後,會在命令面板中新增「複製當前筆記鏈接」和「生成並複製當前塊鏈接」命令', 'auto-block-display-text': '生成塊連結的顯示文本', 'auto-block-display-text-desc': '啟用後,會自動為生成的塊ID連結添加顯示文本', + 'block-display-full-block': '顯示文本取整個塊', + 'block-display-full-block-desc': '啟用後,顯示文本取自整個(多行)塊:軟換行的後續行會用空格拼接。關閉時僅使用單獨一行(舊版行為)。表格、代碼塊和數學塊會回退到塊 ID。', 'block-display-word-limit': '塊顯示文本:英語類語言的單詞數限制', 'block-display-word-limit-desc': '空格分隔語言(如 "this is a sentence")在塊顯示文本中顯示的最大單詞數', 'block-display-char-limit': '塊顯示文本:CJK 類語言的字符數限制', diff --git a/src/linkBuilder.test.ts b/src/linkBuilder.test.ts index 307b742..dc5c905 100644 --- a/src/linkBuilder.test.ts +++ b/src/linkBuilder.test.ts @@ -790,6 +790,13 @@ describe('extractBlockDisplayText', () => { const result = extractBlockDisplayText('value is 2^10 here', 'fallback', 99, 99); expect(result).toBe('value is 2^10 here'); }); + + it('strips pipes that would break the wiki link alias', () => { + const result = extractBlockDisplayText('| col1 | col2 |', 'fallback', 99, 99); + expect(result).not.toContain('|'); + expect(result).toContain('col1'); + expect(result).toContain('col2'); + }); }); describe('English text', () => { diff --git a/src/linkBuilder.ts b/src/linkBuilder.ts index 117ecde..5cc2774 100644 --- a/src/linkBuilder.ts +++ b/src/linkBuilder.ts @@ -198,7 +198,8 @@ export function extractBlockDisplayText( .replace(/^- /, '')) .filter((line) => line.length > 0) .join(' '); - text = text.replace(/=|\*|\[|\]|\(|\)|`|>\s+/g, ''); + // | 会截断 wiki 链接的别名(也可能撑破表格),所以和其他语法字符一起去掉 + text = text.replace(/=|\*|\[|\]|\(|\)|`|\||>\s+/g, ''); if (!text) return blockId; diff --git a/src/main.ts b/src/main.ts index f1ec885..0303603 100644 --- a/src/main.ts +++ b/src/main.ts @@ -332,6 +332,8 @@ export default class EasyCopy extends Plugin { * `- ` 行或段落开头),向下延伸到所有软换行的后续行;每行去掉行尾的 * 块 ID 后用换行拼接。显示文本由 extractBlockDisplayText 合并为一行 * (换行 → 空格),这样多行块的链接别名不再被截断成单独一行。 + * 表格/代码块/数学块等非纯文本块返回空字符串——调用方会回退到 + * 块 ID 作为显示文本(与旧版对这类块的兜底行为一致)。 */ private getBlockText(editor: Editor, cursorLine: number): string { let start = cursorLine; @@ -352,7 +354,12 @@ export default class EasyCopy extends Plugin { } const lines: string[] = []; for (let i = start; i <= end; i++) { - lines.push(editor.getLine(i).replace(/\s*\^[a-zA-Z0-9_-]+\s*$/, '')); + const line = editor.getLine(i); + const trimmed = line.trim(); + if (trimmed.startsWith('|') || trimmed.startsWith('```') || trimmed.startsWith('$$')) { + return ''; + } + lines.push(line.replace(/\s*\^[a-zA-Z0-9_-]+\s*$/, '')); } return lines.join('\n'); } @@ -630,8 +637,12 @@ export default class EasyCopy extends Plugin { switch (contextType.type) { case ContextType.BLOCKID: - // 传整个 block 的文本(而不是单独一行),多行块的别名才完整 - this.copyBlockLink(contextType.match!, filename, true, this.getBlockText(editor, editor.getCursor().line)); + // 显示文本来源:设置开启时取整个 block 的文本(多行块的别名才完整), + // 否则保持旧行为,仅用检测到块 ID 的那一行 + this.copyBlockLink(contextType.match!, filename, true, + this.settings.blockDisplayFullBlock + ? this.getBlockText(editor, editor.getCursor().line) + : contextType.curLine); return; case ContextType.BOLD: void navigator.clipboard.writeText(contextType.match!); @@ -895,9 +906,12 @@ export default class EasyCopy extends Plugin { // —— 新逻辑:定位 block(段落)末尾 —— const cursor = editor.getCursor(); - const { end } = this.detectBlockRange(editor, cursor.line); - // 在插入块 ID 之前取整个 block 的文本作为显示文本(多行 → 一行) - const blockText = this.getBlockText(editor, cursor.line); + const { start, end } = this.detectBlockRange(editor, cursor.line); + // 在插入块 ID 之前取显示文本来源:设置开启时取整个 block 的文本 + // (多行 → 一行),否则保持旧行为,仅用 block 的第一行 + const blockText = this.settings.blockDisplayFullBlock + ? this.getBlockText(editor, cursor.line) + : editor.getLine(start); const lastLine = editor.getLine(end); // 检查 block 最后一行末是否已有块ID diff --git a/src/settingTab.ts b/src/settingTab.ts index d0535c3..39c244f 100644 --- a/src/settingTab.ts +++ b/src/settingTab.ts @@ -303,6 +303,17 @@ export class EasyCopySettingTab extends PluginSettingTab { // 新增:块显示文本限制设置,仅在启用 autoBlockDisplayText 时显示 if (this.plugin.settings.autoBlockDisplayText) { + blockIdGroup.addSetting(setting => setting + .setName(this.plugin.t('block-display-full-block')) + .setDesc(this.plugin.t('block-display-full-block-desc')) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.blockDisplayFullBlock) + .onChange( value => { + this.plugin.settings.blockDisplayFullBlock = value; + void this.plugin.saveSettings(); + }) + )); + blockIdGroup.addSetting(setting => setting .setName(this.plugin.t('block-display-word-limit')) .setDesc(this.plugin.t('block-display-word-limit-desc')) diff --git a/src/type.ts b/src/type.ts index 404b868..636eba8 100644 --- a/src/type.ts +++ b/src/type.ts @@ -71,6 +71,7 @@ export interface EasyCopySettings { allowManualBlockId: boolean; // 是否允许手动输入 Block ID blockIdInsertPosition: BlockIdInsertPosition; // 块ID的插入位置 autoBlockDisplayText: boolean; // 自动为 Block 添加显示文本 + blockDisplayFullBlock: boolean; // 显示文本取整个(多行)块;关闭时与旧版一致仅取单行 blockDisplayWordLimit: number; // Block 显示文本英文单词限制(按空格分隔) blockDisplayCharLimit: number; // Block 显示文本字符限制(非英文语言) enableDisplayNameRegex: boolean; // 是否启用正则替换显示名称 @@ -108,6 +109,7 @@ export const DEFAULT_SETTINGS: EasyCopySettings = { allowManualBlockId: false, // 默认关闭 blockIdInsertPosition: BlockIdInsertPosition.END_OF_BLOCK, // 默认在块末尾插入 autoBlockDisplayText: true, + blockDisplayFullBlock: false, // 默认关闭:保持旧的单行行为 blockDisplayWordLimit: 3, // 英文单词限制:3个单词 blockDisplayCharLimit: 5, // 字符限制:5个字符 enableDisplayNameRegex: false,