fix: restore simplifiedHeadingToNoteLink in OBSIDIAN mode, remove defaultPrevented check, update i18n descriptions

This commit is contained in:
Moy 2026-05-08 13:37:26 +08:00
parent 7c6aa950af
commit fbd9547bf8
5 changed files with 6 additions and 138 deletions

110
package-lock.json generated
View file

@ -26,31 +26,6 @@
"vitest": "^4.1.4"
}
},
"node_modules/@codemirror/state": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.0.tgz",
"integrity": "sha512-MwBHVK60IiIHDcoMet78lxt6iw5gJOGSbNbOIVBHWVXIH4/Nq1+GQgLLGgI1KlnN86WDXsPudVaqYHKBIx7Eyw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@marijn/find-cluster-break": "^1.0.0"
}
},
"node_modules/@codemirror/view": {
"version": "6.38.6",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.6.tgz",
"integrity": "sha512-qiS0z1bKs5WOvHIAC0Cybmv4AJSkAXgX5aD6Mqd2epSLlVJsQl8NG23jCVouIgkh4All/mrbdsf2UOLFnJw0tw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@codemirror/state": "^6.5.0",
"crelt": "^1.0.6",
"style-mod": "^4.1.0",
"w3c-keyname": "^2.2.4"
}
},
"node_modules/@emnapi/core": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz",
@ -638,23 +613,6 @@
"url": "https://eslint.org/donate"
}
},
"node_modules/@eslint/json": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/@eslint/json/-/json-0.14.0.tgz",
"integrity": "sha512-rvR/EZtvUG3p9uqrSmcDJPYSH7atmWr0RnFWN6m917MAPx82+zQgPUmDu0whPFG6XTyM0vB/hR6c1Q63OaYtCQ==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@eslint/core": "^0.17.0",
"@eslint/plugin-kit": "^0.4.1",
"@humanwhocodes/momoa": "^3.3.10",
"natural-compare": "^1.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/object-schema": {
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
@ -717,17 +675,6 @@
"url": "https://github.com/sponsors/nzakas"
}
},
"node_modules/@humanwhocodes/momoa": {
"version": "3.3.10",
"resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-3.3.10.tgz",
"integrity": "sha512-KWiFQpSAqEIyrTXko3hFNLeQvSK8zXlJQzhhxsyVn58WFRYXST99b3Nqnu+ttOtjds2Pl2grUHGpe2NzhPynuQ==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/@humanwhocodes/retry": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
@ -749,14 +696,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/@marijn/find-cluster-break": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
"dev": true,
"license": "MIT",
"peer": true
},
"node_modules/@microsoft/eslint-plugin-sdl": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@microsoft/eslint-plugin-sdl/-/eslint-plugin-sdl-1.1.0.tgz",
@ -1975,14 +1914,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/crelt": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
"dev": true,
"license": "MIT",
"peer": true
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@ -5569,14 +5500,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/style-mod": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz",
"integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==",
"dev": true,
"license": "MIT",
"peer": true
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@ -5852,31 +5775,6 @@
"node": ">=14.17"
}
},
"node_modules/typescript-eslint": {
"version": "8.59.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.0.tgz",
"integrity": "sha512-BU3ONW9X+v90EcCH9ZS6LMackcVtxRLlI3XrYyqZIwVSHIk7Qf7bFw1z0M9Q0IUxhTMZCf8piY9hTYaNEIASrw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.59.0",
"@typescript-eslint/parser": "8.59.0",
"@typescript-eslint/typescript-estree": "8.59.0",
"@typescript-eslint/utils": "8.59.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/unbox-primitive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
@ -6081,14 +5979,6 @@
}
}
},
"node_modules/w3c-keyname": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
"dev": true,
"license": "MIT",
"peer": true
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View file

@ -109,7 +109,7 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
'markdown-link': 'Markdown link',
'wiki-link': 'Wiki link',
'resolve-link-path-on-paste': 'Resolve link path on paste',
'resolve-link-path-on-paste-desc': 'Regenerate the link path at paste time based on the destination file. Under "Follow Obsidian settings", uses your vault\'s path style (shortest/relative/absolute); under explicit Wiki/Markdown, uses shortest-unique paths only. Won\'t interfere with other paste-handling plugins; if one handles the paste first, this feature may be bypassed depending on how that plugin handles the paste.',
'resolve-link-path-on-paste-desc': 'Regenerate the link path at paste time based on the destination file. Under "Follow Obsidian settings", uses your vault\'s path style (shortest/relative/absolute); otherwise uses shortest-unique paths only. Note: when enabled, multiple plugins may handle paste simultaneously, which could cause conflicts.',
'customize-targets': 'Customize targets',
'customize-targets-desc': 'Enable to customize which elements can be copied (disable to copy all elements)',
'enable-inline-code': 'Enable inline code',
@ -209,7 +209,7 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
'markdown-link': 'Markdown链接',
'wiki-link': 'Wiki链接',
'resolve-link-path-on-paste': '粘贴时解析链接路径',
'resolve-link-path-on-paste-desc': '粘贴时根据目标文件重新生成链接路径。使用"跟随 Obsidian 设置"时,会沿用 Obsidian 的路径风格(最短/相对/绝对);选择明确的 Wiki/Markdown 格式时,仅使用最短唯一路径。不会干扰其他处理粘贴的插件;若有其他插件先处理粘贴,此功能可能被绕过,具体取决于该插件的处理方式。',
'resolve-link-path-on-paste-desc': '粘贴时根据目标文件重新生成链接路径。使用"跟随 Obsidian 设置"时,会沿用软件设置中的路径风格(最短/相对/绝对);否则,仅使用最短唯一路径。注:启用后,多个插件可能同时处理粘贴行为,导致冲突。',
'customize-targets': '自定义复制对象',
'customize-targets-desc': '启用后可以自定义哪些元素可以被复制(不启用则默认可复制所有元素)',
'enable-inline-code': '启用行内代码',
@ -319,7 +319,7 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
'markdown-link': 'Markdown連結',
'wiki-link': 'Wiki連結',
'resolve-link-path-on-paste': '貼上時解析連結路徑',
'resolve-link-path-on-paste-desc': '貼上時根據目標檔案重新生成連結路徑。使用「跟隨 Obsidian 設定」時,會沿用 Obsidian 的路徑風格(最短/相對/絕對);選擇明確的 Wiki/Markdown 格式時,僅使用最短唯一路徑。不會干擾其他處理貼上的外掛;若有其他外掛先處理貼上,此功能可能被略過,具體取決於該外掛的處理方式。',
'resolve-link-path-on-paste-desc': '貼上時根據目標檔案重新生成連結路徑。使用「跟隨 Obsidian 設定」時,會沿用軟體設定中的路徑風格(最短/相對/絕對);否則,僅使用最短唯一路徑。注:啟用後,多個外掛可能同時處理貼上行為,導致衝突。',
'customize-targets': '自定義複製對象',
'customize-targets-desc': '啟用後可以自定義哪些元素可以被複製(不啟用則默认可複製所有元素)',
'enable-inline-code': '啟用行內代碼',

View file

@ -169,13 +169,12 @@ export default class EasyCopy extends Plugin {
* // Wiki/Markdown
* fileToLinktext()
*
* editor-paste obsidian.d.ts
* preventDefault preventDefault
* Easy Copy
* defaultPrevented Linter
*/
private handlePaste(evt: ClipboardEvent, editor: Editor, info: MarkdownView | MarkdownFileInfo): void {
const clipboardText = evt.clipboardData?.getData('text/plain');
const decision = decidePasteResolution({
defaultPrevented: evt.defaultPrevented,
resolveLinkPathOnPaste: this.settings.resolveLinkPathOnPaste,
lastCopyMeta: this.lastCopyMeta,
clipboardText,
@ -708,10 +707,6 @@ export default class EasyCopy extends Plugin {
}
}
// 「跟随 Obsidian 设置」时应将格式与路径选择交给 Obsidian
// 此时 simplifiedHeadingToNoteLink 的链接转换会与该原则冲突。
// 在调用点直接禁用该选项,让 buildHeadingLink 保持与格式无关。
const userExplicitlyPickedFormat = this.settings.linkFormat !== LinkFormat.OBSIDIAN;
const { link, isNoteLink } = buildHeadingLink({
heading: content,
filename,
@ -720,8 +715,7 @@ export default class EasyCopy extends Plugin {
useHeadingAsDisplayText: this.settings.useHeadingAsDisplayText,
headingLinkSeparator: this.settings.headingLinkSeparator,
strictHeadingMatch: this.settings.strictHeadingMatch,
simplifiedHeadingToNoteLink:
userExplicitlyPickedFormat && this.settings.simplifiedHeadingToNoteLink,
simplifiedHeadingToNoteLink: this.settings.simplifiedHeadingToNoteLink,
});
navigator.clipboard.writeText(link);

View file

@ -30,7 +30,6 @@ const META: CopyMetadata = {
const TTL = 5 * 60 * 1000;
const baseInput: PasteResolutionInput = {
defaultPrevented: false,
resolveLinkPathOnPaste: true,
lastCopyMeta: META,
clipboardText: META.clipboardText,
@ -43,10 +42,6 @@ describe('decidePasteResolution', () => {
expect(decidePasteResolution(baseInput)).toBe('rewrite');
});
it('skips when another handler already preventDefault\'d', () => {
expect(decidePasteResolution({ ...baseInput, defaultPrevented: true })).toBe('skip');
});
it('skips when the toggle is off', () => {
expect(decidePasteResolution({ ...baseInput, resolveLinkPathOnPaste: false })).toBe('skip');
});
@ -83,15 +78,6 @@ describe('decidePasteResolution', () => {
})).toBe('reset-and-skip');
});
it('defaultPrevented takes precedence over toggle and other state', () => {
expect(decidePasteResolution({
...baseInput,
defaultPrevented: true,
resolveLinkPathOnPaste: false,
lastCopyMeta: null,
})).toBe('skip');
});
it('toggle takes precedence over meta state', () => {
expect(decidePasteResolution({
...baseInput,

View file

@ -18,7 +18,6 @@ export type PasteResolutionAction =
| 'rewrite'; // 重新生成链接并替换粘贴内容
export interface PasteResolutionInput {
defaultPrevented: boolean;
resolveLinkPathOnPaste: boolean;
lastCopyMeta: CopyMetadata | null;
clipboardText: string | undefined;
@ -27,7 +26,6 @@ export interface PasteResolutionInput {
}
export function decidePasteResolution(input: PasteResolutionInput): PasteResolutionAction {
if (input.defaultPrevented) return 'skip';
if (!input.resolveLinkPathOnPaste) return 'skip';
if (!input.lastCopyMeta) return 'skip';
if (input.now - input.lastCopyMeta.timestamp > input.ttlMs) return 'reset-and-skip';