mirror of
https://github.com/moyf/easy-copy.git
synced 2026-07-22 05:43:47 +00:00
feat: support configurable block ID insertion position
This commit is contained in:
parent
bf98aeaa09
commit
79805db2e8
4 changed files with 70 additions and 8 deletions
17
src/i18n.ts
17
src/i18n.ts
|
|
@ -34,6 +34,8 @@ export type TranslationKey =
|
||||||
| 'callout-copy-priority' | 'callout-copy-priority-desc'
|
| 'callout-copy-priority' | 'callout-copy-priority-desc'
|
||||||
| 'auto-add-block-id' | 'auto-add-block-id-desc'
|
| 'auto-add-block-id' | 'auto-add-block-id-desc'
|
||||||
| 'manual-block-id' | 'manual-block-id-desc'
|
| 'manual-block-id' | 'manual-block-id-desc'
|
||||||
|
| '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'
|
| '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-word-limit' | 'block-display-word-limit-desc'
|
| 'block-display-word-limit' | 'block-display-word-limit-desc'
|
||||||
|
|
@ -49,6 +51,11 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
|
||||||
'auto-add-block-id-desc': 'When enabled, if there is no copyable content, a random block ID (^xxxx) will be automatically added to the end of the current line.' ,
|
'auto-add-block-id-desc': 'When enabled, if there is no copyable content, a random block ID (^xxxx) will be automatically added to the end of the current line.' ,
|
||||||
'manual-block-id': 'Manually enter Block ID',
|
'manual-block-id': 'Manually enter Block ID',
|
||||||
'manual-block-id-desc': 'If enabled, you will be prompted to enter a block ID manually.',
|
'manual-block-id-desc': 'If enabled, you will be prompted to enter a block ID manually.',
|
||||||
|
'block-id-insert-position': 'Block ID insert position',
|
||||||
|
'block-id-insert-position-desc': 'Choose where to insert the block ID - For special blocks like code blocks and quote blocks, at least one line break will be inserted.',
|
||||||
|
'block-id-end-of-block': 'End of current block',
|
||||||
|
'block-id-next-line': 'Next line below current block',
|
||||||
|
'block-id-next-line-with-gap': 'Two lines below current block (with empty line)',
|
||||||
'modal-block-id': 'Enter block ID',
|
'modal-block-id': 'Enter block ID',
|
||||||
'modal-block-id-desc': 'Allowed: letters, numbers, hyphens (-), underscores (_). Spaces will be converted to hyphens.',
|
'modal-block-id-desc': 'Allowed: letters, numbers, hyphens (-), underscores (_). Spaces will be converted to hyphens.',
|
||||||
'error-block-id-empty': 'Block ID cannot be empty',
|
'error-block-id-empty': 'Block ID cannot be empty',
|
||||||
|
|
@ -144,6 +151,11 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
|
||||||
'auto-add-block-id-desc': '启用后,如果没有可复制内容时会自动在当前文本末尾添加一个随机生成的块ID(^xxxx)',
|
'auto-add-block-id-desc': '启用后,如果没有可复制内容时会自动在当前文本末尾添加一个随机生成的块ID(^xxxx)',
|
||||||
'manual-block-id': '手动输入块ID',
|
'manual-block-id': '手动输入块ID',
|
||||||
'manual-block-id-desc': '启用后,可以在弹窗中手动输入块ID',
|
'manual-block-id-desc': '启用后,可以在弹窗中手动输入块ID',
|
||||||
|
'block-id-insert-position': '块ID插入位置',
|
||||||
|
'block-id-insert-position-desc': '选择生成块ID时的插入位置。对于代码块和引用块等特殊段落,至少会插入一个换行。',
|
||||||
|
'block-id-end-of-block': '当前块的末尾',
|
||||||
|
'block-id-next-line': '当前块的下方一行',
|
||||||
|
'block-id-next-line-with-gap': '当前块的下方两行(中间隔一个空行)',
|
||||||
'modal-block-id': '输入块ID',
|
'modal-block-id': '输入块ID',
|
||||||
'modal-block-id-desc': '仅允许字母、数字、短横线(-)、下划线(_),空格会自动转为短横线。',
|
'modal-block-id-desc': '仅允许字母、数字、短横线(-)、下划线(_),空格会自动转为短横线。',
|
||||||
'error-block-id-empty': '块ID不能为空',
|
'error-block-id-empty': '块ID不能为空',
|
||||||
|
|
@ -245,6 +257,11 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
|
||||||
'block-display-char-limit-desc': '非空格分隔語言(如中文 "這是一句話")在塊顯示文本中顯示的最大字符數——當第一行包含非ASCII字符時,會採用此設置。',
|
'block-display-char-limit-desc': '非空格分隔語言(如中文 "這是一句話")在塊顯示文本中顯示的最大字符數——當第一行包含非ASCII字符時,會採用此設置。',
|
||||||
'manual-block-id': '手動輸入塊ID',
|
'manual-block-id': '手動輸入塊ID',
|
||||||
'manual-block-id-desc': '啟用後,可以在彈窗中手動輸入塊ID',
|
'manual-block-id-desc': '啟用後,可以在彈窗中手動輸入塊ID',
|
||||||
|
'block-id-insert-position': '塊ID插入位置',
|
||||||
|
'block-id-insert-position-desc': '選擇生成塊ID時的插入位置。對於代碼塊和引用塊等特殊段落,至少會插入一個換行。',
|
||||||
|
'block-id-end-of-block': '當前塊的末尾',
|
||||||
|
'block-id-next-line': '當前塊的下方一行',
|
||||||
|
'block-id-next-line-with-gap': '當前塊的下方兩行(中間隔一個空行)',
|
||||||
'modal-block-id': '輸入塊ID',
|
'modal-block-id': '輸入塊ID',
|
||||||
'modal-block-id-desc': '僅允許字母、數字、連字號(-)、底線(_),空格會自動轉為連字號。',
|
'modal-block-id-desc': '僅允許字母、數字、連字號(-)、底線(_),空格會自動轉為連字號。',
|
||||||
'error-block-id-empty': '塊ID 不能為空',
|
'error-block-id-empty': '塊ID 不能為空',
|
||||||
|
|
|
||||||
36
src/main.ts
36
src/main.ts
|
|
@ -1,6 +1,6 @@
|
||||||
import { Editor, MarkdownView, Notice, Plugin, Menu, Platform, MarkdownFileInfo } from 'obsidian';
|
import { Editor, MarkdownView, Notice, Plugin, Menu, Platform, MarkdownFileInfo } from 'obsidian';
|
||||||
import { Language, TranslationKey, I18n } from './i18n';
|
import { Language, TranslationKey, I18n } from './i18n';
|
||||||
import { ContextData, ContextType, DEFAULT_SETTINGS, EasyCopySettings, LinkFormat } from './type';
|
import { ContextData, ContextType, DEFAULT_SETTINGS, EasyCopySettings, LinkFormat, BlockIdInsertPosition } from './type';
|
||||||
import { EasyCopySettingTab } from './settingTab';
|
import { EasyCopySettingTab } from './settingTab';
|
||||||
import { BlockIdInputModal } from './blockIdModal';
|
import { BlockIdInputModal } from './blockIdModal';
|
||||||
|
|
||||||
|
|
@ -134,7 +134,7 @@ export default class EasyCopy extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检测光标所在行末尾或下一行开头的 block ID
|
* 检测光标所在行末尾或下 1~2 行开头的 block ID
|
||||||
*/
|
*/
|
||||||
private detectBlockRange(editor: Editor, cursorLine: number): { start: number, end: number } {
|
private detectBlockRange(editor: Editor, cursorLine: number): { start: number, end: number } {
|
||||||
// 如果当前行是列表,那么范围就是当前行(不对,要继续延伸到后面的……只能说开头是定了)
|
// 如果当前行是列表,那么范围就是当前行(不对,要继续延伸到后面的……只能说开头是定了)
|
||||||
|
|
@ -147,14 +147,17 @@ export default class EasyCopy extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalLines = editor.lineCount();
|
const totalLines = editor.lineCount();
|
||||||
|
|
||||||
let start = cursorLine;
|
let start = cursorLine;
|
||||||
while (start > 0 && this.isContinuousText(editor.getLine(start - 1))) {
|
while (start > 0 && this.isContinuousText(editor.getLine(start - 1))) {
|
||||||
start--;
|
start--;
|
||||||
}
|
}
|
||||||
|
|
||||||
let end = cursorLine;
|
let end = cursorLine;
|
||||||
while (end < totalLines - 1 && this.isContinuousText(editor.getLine(end + 1))) {
|
while (end < totalLines - 1 && this.isContinuousText(editor.getLine(end + 1))) {
|
||||||
end++;
|
end++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { start, end };
|
return { start, end };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,7 +264,7 @@ export default class EasyCopy extends Plugin {
|
||||||
{ type: ContextType.HIGHLIGHT, regex: /==([^=]+)==/g , enable: !this.settings.customizeTargets || this.settings.enableHighlight},
|
{ type: ContextType.HIGHLIGHT, regex: /==([^=]+)==/g , enable: !this.settings.customizeTargets || this.settings.enableHighlight},
|
||||||
{ type: ContextType.STRIKETHROUGH, regex: /~~([^~]+)~~/g , enable: !this.settings.customizeTargets || this.settings.enableStrikethrough},
|
{ type: ContextType.STRIKETHROUGH, regex: /~~([^~]+)~~/g , enable: !this.settings.customizeTargets || this.settings.enableStrikethrough},
|
||||||
{ type: ContextType.INLINECODE, regex: /`([^`]+)`/g , enable: !this.settings.customizeTargets || this.settings.enableInlineCode},
|
{ type: ContextType.INLINECODE, regex: /`([^`]+)`/g , enable: !this.settings.customizeTargets || this.settings.enableInlineCode},
|
||||||
{ type: ContextType.INLINELATEX, regex: /\$([^$]*)\$/g , enable: !this.settings.customizeTargets || this.settings.enableInlineLatex},
|
{ type: ContextType.INLINELATEX, regex: /\$([^$]+)\$/g , enable: !this.settings.customizeTargets || this.settings.enableInlineLatex},
|
||||||
{ type: ContextType.WIKILINK, regex: /\[\[([^\]]+)\]\]/g, enable: !this.settings.customizeTargets || this.settings.enableWikiLink },
|
{ type: ContextType.WIKILINK, regex: /\[\[([^\]]+)\]\]/g, enable: !this.settings.customizeTargets || this.settings.enableWikiLink },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -745,11 +748,30 @@ export default class EasyCopy extends Plugin {
|
||||||
if (!/\^[a-zA-Z0-9_-]+$/.test(lastLine.trim())) {
|
if (!/\^[a-zA-Z0-9_-]+$/.test(lastLine.trim())) {
|
||||||
// 在 block 最后一行末尾插入块ID
|
// 在 block 最后一行末尾插入块ID
|
||||||
let insertText = '^' + blockId;
|
let insertText = '^' + blockId;
|
||||||
|
|
||||||
|
// 代码块、引用块、数学块等
|
||||||
|
const isSpecialBlock = lastLine.startsWith('> ') || lastLine.startsWith('```') || lastLine.startsWith('$$');
|
||||||
|
const needsSeparator = lastLine.trim().length > 0 && !lastLine.endsWith(' '); // 末尾需要空格分隔符
|
||||||
|
|
||||||
if (lastLine.startsWith('> ') || lastLine.startsWith('``')) {
|
// 添加 block id 到末尾——读取设置中的位置
|
||||||
insertText = '\n' + insertText;
|
const insertPosition = this.settings.blockIdInsertPosition;
|
||||||
} else if ( lastLine.trim().length > 0 && !lastLine.endsWith(' ')) {
|
|
||||||
insertText = ' ' + insertText;
|
if (isSpecialBlock) {
|
||||||
|
insertText = "\n" + insertText;
|
||||||
|
} else {
|
||||||
|
switch (insertPosition) {
|
||||||
|
case BlockIdInsertPosition.END_OF_BLOCK:
|
||||||
|
if (needsSeparator) {
|
||||||
|
insertText = ' ' + insertText;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BlockIdInsertPosition.NEXT_LINE:
|
||||||
|
insertText = "\n" + insertText;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
insertText = "\n" + insertText;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.replaceRange(insertText, { line: end, ch: lastLine.length });
|
editor.replaceRange(insertText, { line: end, ch: lastLine.length });
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { App, PluginSettingTab, Setting } from "obsidian";
|
import { App, PluginSettingTab, Setting } from "obsidian";
|
||||||
import EasyCopy from "./main";
|
import EasyCopy from "./main";
|
||||||
import { LinkFormat } from "./type";
|
import { LinkFormat, BlockIdInsertPosition } from "./type";
|
||||||
|
|
||||||
|
|
||||||
export class EasyCopySettingTab extends PluginSettingTab {
|
export class EasyCopySettingTab extends PluginSettingTab {
|
||||||
|
|
@ -145,6 +145,21 @@ export class EasyCopySettingTab extends PluginSettingTab {
|
||||||
this.display();
|
this.display();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
if (this.plugin.settings.autoAddBlockId) {
|
||||||
|
// 新增:块ID插入位置设置
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName(this.plugin.t('block-id-insert-position'))
|
||||||
|
.setDesc(this.plugin.t('block-id-insert-position-desc'))
|
||||||
|
.addDropdown(dropdown => dropdown
|
||||||
|
.addOption(BlockIdInsertPosition.END_OF_BLOCK, this.plugin.t('block-id-end-of-block'))
|
||||||
|
.addOption(BlockIdInsertPosition.NEXT_LINE, this.plugin.t('block-id-next-line'))
|
||||||
|
.setValue(this.plugin.settings.blockIdInsertPosition)
|
||||||
|
.onChange(async (value) => {
|
||||||
|
this.plugin.settings.blockIdInsertPosition = value as BlockIdInsertPosition;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
if (this.plugin.settings.autoAddBlockId) {
|
if (this.plugin.settings.autoAddBlockId) {
|
||||||
new Setting(containerEl)
|
new Setting(containerEl)
|
||||||
.setName(this.plugin.t('manual-block-id'))
|
.setName(this.plugin.t('manual-block-id'))
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,12 @@ export enum LinkFormat {
|
||||||
WIKILINK = 'wiki-link'
|
WIKILINK = 'wiki-link'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum BlockIdInsertPosition {
|
||||||
|
END_OF_BLOCK = 'end-of-block', // 当前块的末尾
|
||||||
|
NEXT_LINE = 'next-line', // 当前块的下方一行
|
||||||
|
// NEXT_LINE_WITH_GAP = 'next-line-with-gap' // 当前块的下方两行(中间隔一个空行)
|
||||||
|
}
|
||||||
|
|
||||||
export enum ContextType {
|
export enum ContextType {
|
||||||
NULL = 'null',
|
NULL = 'null',
|
||||||
HEADING = 'heading',
|
HEADING = 'heading',
|
||||||
|
|
@ -51,6 +57,7 @@ export interface EasyCopySettings {
|
||||||
calloutCopyPriority: boolean; // Callout 与块ID冲突时,优先复制 Callout
|
calloutCopyPriority: boolean; // Callout 与块ID冲突时,优先复制 Callout
|
||||||
autoAddBlockId: boolean; // 是否自动添加 Block ID
|
autoAddBlockId: boolean; // 是否自动添加 Block ID
|
||||||
allowManualBlockId: boolean; // 是否允许手动输入 Block ID
|
allowManualBlockId: boolean; // 是否允许手动输入 Block ID
|
||||||
|
blockIdInsertPosition: BlockIdInsertPosition; // 块ID的插入位置
|
||||||
autoBlockDisplayText: boolean; // 自动为 Block 添加显示文本
|
autoBlockDisplayText: boolean; // 自动为 Block 添加显示文本
|
||||||
blockDisplayWordLimit: number; // Block 显示文本英文单词限制(按空格分隔)
|
blockDisplayWordLimit: number; // Block 显示文本英文单词限制(按空格分隔)
|
||||||
blockDisplayCharLimit: number; // Block 显示文本字符限制(非英文语言)
|
blockDisplayCharLimit: number; // Block 显示文本字符限制(非英文语言)
|
||||||
|
|
@ -81,6 +88,7 @@ export const DEFAULT_SETTINGS: EasyCopySettings = {
|
||||||
calloutCopyPriority: true,
|
calloutCopyPriority: true,
|
||||||
autoAddBlockId: false, // 默认关闭
|
autoAddBlockId: false, // 默认关闭
|
||||||
allowManualBlockId: false, // 默认关闭
|
allowManualBlockId: false, // 默认关闭
|
||||||
|
blockIdInsertPosition: BlockIdInsertPosition.END_OF_BLOCK, // 默认在块末尾插入
|
||||||
autoBlockDisplayText: true,
|
autoBlockDisplayText: true,
|
||||||
blockDisplayWordLimit: 3, // 英文单词限制:3个单词
|
blockDisplayWordLimit: 3, // 英文单词限制:3个单词
|
||||||
blockDisplayCharLimit: 5, // 字符限制:5个字符
|
blockDisplayCharLimit: 5, // 字符限制:5个字符
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue