Merge pull request #2 from RavenHogWarts/more-match

Add more replication type matches.
Refactor the structure of the source codes.
This commit is contained in:
Moy 2025-03-23 18:58:32 +08:00 committed by GitHub
commit 0e96bb3a11
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 458 additions and 322 deletions

View file

@ -7,16 +7,19 @@ export enum Language {
// 定义翻译键值类型
export type TranslationKey =
| 'no-file' | 'no-content' | 'inline-code-copied' | 'block-id-copied'
| 'note-link-copied' | 'heading-copied' | 'format'
| 'add-to-menu' | 'add-to-menu-desc' | 'show-notice' | 'show-notice-desc'
| 'use-heading-as-display' | 'use-heading-as-display-desc' | 'link-format'
| 'link-format-desc' | 'markdown-link' | 'wiki-link' | 'contextual-copy'
| 'target' | 'enable-bold' | 'enable-bold-desc' | 'enable-highlight'
| 'enable-highlight-desc' | 'enable-italic' | 'enable-italic-desc'
| 'bold-copied' | 'highlight-copied' | 'italic-copied'
| 'customize-targets' | 'customize-targets-desc' | 'enable-inline-code'
| 'enable-inline-code-desc';
| 'no-file' | 'no-content'
| 'inline-code-copied' | 'block-id-copied' | 'note-link-copied' | 'heading-copied' | 'strikethrough-copied' | 'inline-latex-copied' | 'link-copied' | 'bold-copied' | 'highlight-copied' | 'italic-copied'
| 'format' | 'add-to-menu' | 'add-to-menu-desc' | 'show-notice' | 'show-notice-desc'
| 'use-heading-as-display' | 'use-heading-as-display-desc'
| 'link-format'| 'link-format-desc' | 'markdown-link' | 'wiki-link' | 'contextual-copy'
| 'target' | 'customize-targets' | 'customize-targets-desc'
| 'enable-bold' | 'enable-bold-desc'
| 'enable-highlight'| 'enable-highlight-desc'
| 'enable-italic' | 'enable-italic-desc'
| 'enable-inline-code' | 'enable-inline-code-desc'
| 'enable-strikethrough' | 'enable-strikethrough-desc'
| 'enable-inline-latex' | 'enable-inline-latex-desc'
| 'enable-link' | 'enable-link-desc';
// 本地化翻译字典
export const translations: Record<Language, Record<TranslationKey, string>> = {
@ -31,6 +34,9 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
'bold-copied': 'Bold text copied!',
'highlight-copied': 'Highlighted text copied!',
'italic-copied': 'Italic text copied!',
'inline-latex-copied': 'Inline LaTeX copied!',
'strikethrough-copied': 'Strikethrough text copied!',
'link-copied': 'Link copied!',
// 设置界面
'format': 'Format',
@ -55,6 +61,12 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
'enable-highlight-desc': 'Enable copying highlighted text like ==highlight example==',
'enable-italic': 'Enable italic text',
'enable-italic-desc': 'Enable copying italic text like *italic example*',
'enable-strikethrough': 'Enable strikethrough text',
'enable-strikethrough-desc': 'Enable copying strikethrough text like ~~strikethrough example~~',
'enable-inline-latex': 'Enable inline LaTeX',
'enable-inline-latex-desc': 'Enable copying inline LaTeX like $latex example$',
'enable-link': 'Enable link',
'enable-link-desc': 'Enable copying link like [linktitle example](linkurl example)',
// 命令名称
'contextual-copy': 'Contextual Copy'
@ -70,6 +82,9 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
'bold-copied': '加粗文本已复制!',
'highlight-copied': '高亮文本已复制!',
'italic-copied': '斜体文本已复制!',
'inline-latex-copied': '行内LaTeX已复制',
'strikethrough-copied': '删除线文本已复制!',
'link-copied': '链接已复制!',
// 设置界面
'format': '格式',
@ -94,6 +109,12 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
'enable-highlight-desc': '启用复制高亮文本,如 ==高亮示例==',
'enable-italic': '启用斜体文本',
'enable-italic-desc': '启用复制斜体文本,如 *斜体示例*',
'enable-strikethrough': '启用删除线文本',
'enable-strikethrough-desc': '启用复制删除线文本,如 ~~删除线示例~~',
'enable-inline-latex': '启用行内LaTeX',
'enable-inline-latex-desc': '启用复制行内LaTeX如 $latex 示例$',
'enable-link': '启用链接',
'enable-link-desc': '启用复制链接,如 [链接标题 示例](链接地址 示例)',
// 命令名称
'contextual-copy': '智能复制'
@ -109,6 +130,9 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
'bold-copied': '加粗文本已複製!',
'highlight-copied': '高亮文本已複製!',
'italic-copied': '斜體文本已複製!',
'inline-latex-copied': '行內LaTeX已複製',
'strikethrough-copied': '刪除線文本已複製!',
'link-copied': '連結已複製!',
// 設置界面
'format': '格式',
@ -133,6 +157,12 @@ export const translations: Record<Language, Record<TranslationKey, string>> = {
'enable-highlight-desc': '啟用複製高亮文本,如 ==高亮示例==',
'enable-italic': '啟用斜體文本',
'enable-italic-desc': '啟用複製斜體文本,如 *斜體示例*',
'enable-strikethrough': '啟用刪除線文本',
'enable-strikethrough-desc': '啟用複製刪除線文本,如 ~~刪除線示例~~',
'enable-inline-latex': '啟用行內LaTeX',
'enable-inline-latex-desc': '啟用複製行內LaTeX如 $latex 示例$',
'enable-link': '啟用連結',
'enable-link-desc': '啟用複製連結,如 [連結標題 示例](連結地址 示例)',
// 命令名称
'contextual-copy': '智能複製'

View file

@ -1,34 +1,7 @@
import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting, Menu } from 'obsidian';
import { Editor, MarkdownView, Notice, Plugin, Menu } from 'obsidian';
import { Language, TranslationKey, I18n } from './i18n';
enum LinkFormat {
MDLINK = 'markdown-link',
WIKILINK = 'wiki-link'
}
interface EasyCopySettings {
addToMenu: boolean;
showNotice: boolean;
useHeadingAsDisplayText: boolean;
linkFormat: LinkFormat;
customizeTargets: boolean;
enableInlineCode: boolean;
enableBold: boolean;
enableHighlight: boolean;
enableItalic: boolean;
}
const DEFAULT_SETTINGS: EasyCopySettings = {
addToMenu: true,
showNotice: true,
useHeadingAsDisplayText: true,
linkFormat: LinkFormat.WIKILINK,
customizeTargets: false,
enableInlineCode: true,
enableBold: true,
enableHighlight: true,
enableItalic: false
}
import { ContextData, ContextType, DEFAULT_SETTINGS, EasyCopySettings, LinkFormat } from './type';
import { EasyCopySettingTab } from './settingTab';
export default class EasyCopy extends Plugin {
settings: EasyCopySettings;
@ -115,6 +88,140 @@ export default class EasyCopy extends Plugin {
return this.i18n.t(key);
}
/**
*
* @param editor
* @param view
* @returns ContextData
*/
private determineContextType(editor: Editor, view: MarkdownView): ContextData {
// 获取当前文件和光标信息
const file = view.file;
if (!file) {
new Notice(this.t('no-file'));
return { type: ContextType.NULL, curLine: '', match: null, range: null };
}
const cursor = editor.getCursor();
const curLine = editor.getLine(cursor.line);
const curCh = cursor.ch;
// 根据光标位置解析内容类型
const beforeCursor = curLine.slice(0, curCh); // 光标前的内容
const afterCursor = curLine.slice(curCh); // 光标后的内容
// 匹配优先级:加粗 > 斜体 > 高亮 > 删除线 > 行内代码 > 行内Latex > 块ID
const matchers = [
{ type: ContextType.BOLD, regex: /\*\*([^*]+)\*\*/g , enable: this.settings.enableBold},
// 使用前后断言 (?<!\*) 和 (?!\*),确保 * 不被包裹在 ** 中。
{ type: ContextType.ITALIC, regex: /(?<!\*)\*([^*]+)\*(?!\*)/g , enable: this.settings.customizeTargets && this.settings.enableItalic},
{ 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.INLINECODE, regex: /`([^`]+)`/g , enable: this.settings.customizeTargets && this.settings.enableInlineCode},
{ type: ContextType.INLINELATEX, regex: /\$([^$]*)\$/g , enable: this.settings.customizeTargets && this.settings.enableInlineLatex},
{ type: ContextType.BLOCKID, regex: /\^([a-zA-Z0-9_-]+)/g , enable: true}, // 块ID不需要判断enable
];
for (const matcher of matchers) {
if (!matcher.enable) continue; // 如果当前类型未启用,则跳过
const matchInfo = this.getMatchInfo(beforeCursor, afterCursor, matcher.regex);
if (matchInfo) {
return {
type: matcher.type,
curLine,
match: matchInfo.content, // 返回内容,不包括语法
range: matchInfo.range,
};
}
}
// 检测链接
if (this.settings.customizeTargets && this.settings.enableLink) {
const linkInfo = this.isCursorInLink(beforeCursor, afterCursor);
if (linkInfo) {
return {
type: linkInfo.type,
curLine,
match: linkInfo.content,
range: linkInfo.range,
};
}
}
// 如果当前行是标题行,且光标不在其他 Markdown 语法范围内,则返回标题类型
const headingRegex = /^(#+)\s/; // 标题正则表达式
if (headingRegex.test(curLine)) {
const match = curLine.match(headingRegex);
const headingContent = curLine.replace(headingRegex, '').trim();
return {
type: ContextType.HEADING,
curLine,
match: headingContent, // 返回内容,不包括语法
range: match ? [match[0].length, curLine.length] : null,
};
}
// 默认返回空值
return { type: ContextType.NULL, curLine, match: null, range: null };
}
/**
*
* @param beforeCursor
* @param afterCursor
* @param regex
* @returns
*/
private getMatchInfo(beforeCursor: string, afterCursor: string, regex: RegExp): { content: string; range: [number, number] } | null {
let match;
while ((match = regex.exec(beforeCursor + afterCursor)) !== null) {
const matchStart = match.index;
const matchEnd = match.index + match[0].length;
// 判断光标是否在匹配范围内
if (beforeCursor.length >= matchStart && beforeCursor.length <= matchEnd) {
return {
content: match[1], // 返回内容,不包括语法
range: [matchStart, matchEnd],
};
}
}
return null;
}
private isCursorInLink(beforeCursor: string, afterCursor: string): {type: ContextType.LINKTITLE | ContextType.LINEURL, content: string, range: [number, number]} | null {
// 匹配链接的正则表达式
const linkRegex = /\[([^\]]*?)\]\(([^)]*?)\)/g;
const fullText = beforeCursor + afterCursor;
let match: RegExpExecArray | null;
while ((match = linkRegex.exec(fullText)) !== null) {
const linkStart = match.index; // 链接的起始位置
const linkEnd = linkStart + match[0].length; // 链接的结束位置
// 光标位置
const cursorPos = beforeCursor.length;
// 判断光标是否在当前链接范围内
if (cursorPos >= linkStart && cursorPos <= linkEnd) {
const bracketStart = linkStart + 1; // `[` 后的位置
const bracketEnd = linkStart + match[1].length + 1; // `]` 的位置
const parenStart = bracketEnd + 2; // `(` 后的位置
const parenEnd = parenStart + match[2].length; // `)` 的位置
// 判断光标在 [] 还是 ()
if (cursorPos >= bracketStart && cursorPos <= bracketEnd) {
return { type: ContextType.LINKTITLE, content: match[1], range: [bracketStart, bracketEnd] };
} else if (cursorPos >= parenStart && cursorPos <= parenEnd) {
return { type: ContextType.LINEURL, content: match[2], range: [parenStart, parenEnd] };
}
}
}
// 如果光标不在任何链接中,返回 null
return null;
}
/**
*
* ID链接和标题链接
@ -126,141 +233,112 @@ export default class EasyCopy extends Plugin {
new Notice(this.t('no-file'));
return;
}
const cursor = editor.getCursor();
const curLine = editor.getLine(cursor.line);
const curCh = cursor.ch;
// 获取文件名(去除.md后缀
const filename = file.basename;
// 1. 检查是否是标题行
if (/^#+\s/.test(curLine)) {
this.copyHeadingLink(curLine, filename);
// 获取当前行的上下文类型
const contextType = this.determineContextType(editor, view);
console.log('contextType:', contextType);
if (contextType.type == ContextType.NULL) {
new Notice(this.t('no-content'));
return;
}
// 2. 检查是否包含行内代码
if ((!this.settings.customizeTargets || this.settings.enableInlineCode) && curLine.includes('`')) {
// 尝试提取行内代码
const inlineCode = this.getInlineCode(curLine, curCh);
if (inlineCode) {
navigator.clipboard.writeText(inlineCode);
if (this.settings.showNotice) {
new Notice(this.t('inline-code-copied'));
}
return;
}
}
// 3. 检查是否包含块ID
if (curLine.includes('^')) {
// 尝试提取块ID
const blockId = this.getBlockId(curLine);
if (blockId) {
const blockIdLink = this.settings.linkFormat === LinkFormat.WIKILINK
? `[[${filename}#^${blockId}]]`
: `[${blockId}](${filename}#^${blockId})`;
navigator.clipboard.writeText(blockIdLink);
if (this.settings.showNotice) {
new Notice(this.t('block-id-copied'));
}
return;
}
}
// 4. 检查是否包含加粗文本
if ((!this.settings.customizeTargets || this.settings.enableBold) && curLine.includes('**')) {
const boldText = this.getBoldText(curLine, curCh);
if (boldText) {
navigator.clipboard.writeText(boldText);
switch (contextType.type) {
case ContextType.BOLD:
navigator.clipboard.writeText(contextType.match!);
if (this.settings.showNotice) {
new Notice(this.t('bold-copied'));
}
return;
}
}
// 5. 检查是否包含高亮文本
if ((!this.settings.customizeTargets || this.settings.enableHighlight) && curLine.includes('==')) {
const highlightText = this.getHighlightText(curLine, curCh);
if (highlightText) {
navigator.clipboard.writeText(highlightText);
if (this.settings.showNotice) {
new Notice(this.t('highlight-copied'));
}
return;
}
}
// 6. 检查是否包含斜体文本
if ((!this.settings.customizeTargets || this.settings.enableItalic) && (curLine.includes('*') || curLine.includes('_'))) {
const italicText = this.getItalicText(curLine, curCh);
if (italicText) {
navigator.clipboard.writeText(italicText);
case ContextType.ITALIC:
navigator.clipboard.writeText(contextType.match!);
if (this.settings.showNotice) {
new Notice(this.t('italic-copied'));
}
return;
}
case ContextType.HIGHLIGHT:
navigator.clipboard.writeText(contextType.match!);
if (this.settings.showNotice) {
new Notice(this.t('highlight-copied'));
}
return;
case ContextType.STRIKETHROUGH:
navigator.clipboard.writeText(contextType.match!);
if (this.settings.showNotice) {
new Notice(this.t('strikethrough-copied'));
}
return;
case ContextType.INLINECODE:
navigator.clipboard.writeText(contextType.match!);
if (this.settings.showNotice) {
new Notice(this.t('inline-code-copied'));
}
return;
case ContextType.INLINELATEX:
navigator.clipboard.writeText(contextType.match!);
if (this.settings.showNotice) {
new Notice(this.t('inline-latex-copied'));
}
return;
case ContextType.LINKTITLE:
case ContextType.LINEURL:
// 复制链接标题或链接地址
navigator.clipboard.writeText(contextType.match!);
if (this.settings.showNotice) {
new Notice(this.t('link-copied'));
}
return;
case ContextType.BLOCKID:
{
const blockIdLink = this.settings.linkFormat === LinkFormat.WIKILINK
? `[[${filename}#^${contextType.match!}]]`
: `[${contextType.match!}](${filename}#^${contextType.match!})`;
navigator.clipboard.writeText(blockIdLink);
}
if (this.settings.showNotice) {
new Notice(this.t('block-id-copied'));
}
return;
case ContextType.HEADING:
this.copyHeadingLink(contextType.match!, filename);
return;
default:
break;
}
// 如果没有找到可复制的内容
new Notice(this.t('no-content'));
}
/**
*
*/
private getInlineCode(str: string, cursor: number): string | null {
const start = str.lastIndexOf('`', cursor - 1);
const end = str.indexOf('`', cursor);
if (start === -1 || end === -1) {
return null;
}
return str.substring(start + 1, end);
}
/**
* ID
*/
private getBlockId(str: string): string | null {
// 提取当前光标所在行的像是 ^block-id-123 这样的 block id
const regex = /(?:^|\s+)\^([a-zA-Z0-9_-]+)(?:\s*|$)/;
const match = str.match(regex);
if (match) {
return match[1];
}
return null;
}
/**
*
*/
private copyHeadingLink(headingLine: string, filename: string): void {
private copyHeadingLink(content: string, filename: string): void {
// 提取标题文本和级别
const selectedHeading = headingLine.replace(/#+\s+/, "#");
const linkAlias = selectedHeading.replace(/#+\s*/, "");
let selectedHeading = content;
// 如果内容是[[内容]],移除[[]]
if (selectedHeading.startsWith('[[') && selectedHeading.endsWith(']]')) {
selectedHeading = selectedHeading.slice(2, -2);
}
const linkAlias = selectedHeading;
let noteFlag = 0;
let headingReferenceLink = "";
// 根据设置选择链接格式
if (this.settings.linkFormat === LinkFormat.WIKILINK) {
// Wiki链接格式
headingReferenceLink = `[[${filename}${selectedHeading}|${linkAlias}]]`;
headingReferenceLink = `[[${filename}#${selectedHeading}|${linkAlias}]]`;
// 处理同名标题的特殊情况
if (this.settings.useHeadingAsDisplayText && filename === linkAlias) {
headingReferenceLink = `[[${filename}]]`;
noteFlag = 1;
}
} else {
// Markdown链接格式
headingReferenceLink = `[${linkAlias}](${filename}${selectedHeading})`;
headingReferenceLink = `[${linkAlias}](${filename}#${selectedHeading})`;
}
// 复制到剪贴板
@ -268,7 +346,7 @@ export default class EasyCopy extends Plugin {
// 显示通知
if (this.settings.showNotice) {
if (headingLine.startsWith("# ")) {
if (noteFlag) {
new Notice(this.t('note-link-copied'));
} else {
new Notice(this.t('heading-copied'));
@ -276,68 +354,6 @@ export default class EasyCopy extends Plugin {
}
}
/**
*
*/
private getBoldText(str: string, cursor: number): string | null {
// 查找光标前后的 ** 标记
const start = str.lastIndexOf('**', cursor - 1);
const end = str.indexOf('**', cursor);
if (start === -1 || end === -1) {
return null;
}
return str.substring(start + 2, end);
}
/**
*
*/
private getHighlightText(str: string, cursor: number): string | null {
// 查找光标前后的 == 标记
const start = str.lastIndexOf('==', cursor - 1);
const end = str.indexOf('==', cursor);
if (start === -1 || end === -1) {
return null;
}
return str.substring(start + 2, end);
}
/**
*
*/
private getItalicText(str: string, cursor: number): string | null {
// 尝试查找使用 * 的斜体
let start = str.lastIndexOf('*', cursor - 1);
if (start > 0 && str.charAt(start - 1) === '*') {
// 这可能是加粗文本的一部分,跳过
start = str.lastIndexOf('*', start - 2);
}
let end = str.indexOf('*', cursor);
if (end > 0 && end + 1 < str.length && str.charAt(end + 1) === '*') {
// 这可能是加粗文本的一部分,跳过
end = str.indexOf('*', end + 2);
}
if (start !== -1 && end !== -1) {
return str.substring(start + 1, end);
}
// 尝试查找使用 _ 的斜体
start = str.lastIndexOf('_', cursor - 1);
end = str.indexOf('_', cursor);
if (start !== -1 && end !== -1) {
return str.substring(start + 1, end);
}
return null;
}
/**
* 使Obsidian的语言设置
*/
@ -371,119 +387,3 @@ export default class EasyCopy extends Plugin {
return lang;
}
}
class EasyCopySettingTab extends PluginSettingTab {
plugin: EasyCopy;
constructor(app: App, plugin: EasyCopy) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const {containerEl} = this;
containerEl.empty();
new Setting(containerEl)
.setName(this.plugin.t('add-to-menu'))
.setDesc(this.plugin.t('add-to-menu-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.addToMenu)
.onChange(async (value) => {
this.plugin.settings.addToMenu = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('show-notice'))
.setDesc(this.plugin.t('show-notice-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.showNotice)
.onChange(async (value) => {
this.plugin.settings.showNotice = value;
await this.plugin.saveSettings();
}));
containerEl.createEl('h2', {text: this.plugin.t('format')});
new Setting(containerEl)
.setName(this.plugin.t('use-heading-as-display'))
.setDesc(this.plugin.t('use-heading-as-display-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.useHeadingAsDisplayText)
.onChange(async (value) => {
this.plugin.settings.useHeadingAsDisplayText = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('link-format'))
.setDesc(this.plugin.t('link-format-desc'))
.addDropdown(dropdown => dropdown
.addOption(LinkFormat.MDLINK, this.plugin.t('markdown-link'))
.addOption(LinkFormat.WIKILINK, this.plugin.t('wiki-link'))
.setValue(this.plugin.settings.linkFormat)
.onChange(async (value) => {
this.plugin.settings.linkFormat = value as LinkFormat;
await this.plugin.saveSettings();
}));
containerEl.createEl('h2', {text: this.plugin.t('target')});
new Setting(containerEl)
.setName(this.plugin.t('customize-targets'))
.setDesc(this.plugin.t('customize-targets-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.customizeTargets)
.onChange(async (value) => {
this.plugin.settings.customizeTargets = value;
await this.plugin.saveSettings();
// 重新渲染设置界面以显示或隐藏目标选项
this.display();
}));
// 只有当自定义复制对象选项开启时才显示具体的复制对象选项
if (this.plugin.settings.customizeTargets) {
new Setting(containerEl)
.setName(this.plugin.t('enable-inline-code'))
.setDesc(this.plugin.t('enable-inline-code-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enableInlineCode)
.onChange(async (value) => {
this.plugin.settings.enableInlineCode = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('enable-bold'))
.setDesc(this.plugin.t('enable-bold-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enableBold)
.onChange(async (value) => {
this.plugin.settings.enableBold = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('enable-highlight'))
.setDesc(this.plugin.t('enable-highlight-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enableHighlight)
.onChange(async (value) => {
this.plugin.settings.enableHighlight = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('enable-italic'))
.setDesc(this.plugin.t('enable-italic-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enableItalic)
.onChange(async (value) => {
this.plugin.settings.enableItalic = value;
await this.plugin.saveSettings();
}));
}
}
}

151
src/settingTab.ts Normal file
View file

@ -0,0 +1,151 @@
import { App, PluginSettingTab, Setting } from "obsidian";
import EasyCopy from "./main";
import { LinkFormat } from "./type";
export class EasyCopySettingTab extends PluginSettingTab {
plugin: EasyCopy;
constructor(app: App, plugin: EasyCopy) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const {containerEl} = this;
containerEl.empty();
new Setting(containerEl)
.setName(this.plugin.t('add-to-menu'))
.setDesc(this.plugin.t('add-to-menu-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.addToMenu)
.onChange(async (value) => {
this.plugin.settings.addToMenu = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('show-notice'))
.setDesc(this.plugin.t('show-notice-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.showNotice)
.onChange(async (value) => {
this.plugin.settings.showNotice = value;
await this.plugin.saveSettings();
}));
containerEl.createEl('h2', {text: this.plugin.t('format')});
new Setting(containerEl)
.setName(this.plugin.t('use-heading-as-display'))
.setDesc(this.plugin.t('use-heading-as-display-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.useHeadingAsDisplayText)
.onChange(async (value) => {
this.plugin.settings.useHeadingAsDisplayText = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('link-format'))
.setDesc(this.plugin.t('link-format-desc'))
.addDropdown(dropdown => dropdown
.addOption(LinkFormat.MDLINK, this.plugin.t('markdown-link'))
.addOption(LinkFormat.WIKILINK, this.plugin.t('wiki-link'))
.setValue(this.plugin.settings.linkFormat)
.onChange(async (value) => {
this.plugin.settings.linkFormat = value as LinkFormat;
await this.plugin.saveSettings();
}));
containerEl.createEl('h2', {text: this.plugin.t('target')});
new Setting(containerEl)
.setName(this.plugin.t('customize-targets'))
.setDesc(this.plugin.t('customize-targets-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.customizeTargets)
.onChange(async (value) => {
this.plugin.settings.customizeTargets = value;
await this.plugin.saveSettings();
// 重新渲染设置界面以显示或隐藏目标选项
this.display();
}));
// 只有当自定义复制对象选项开启时才显示具体的复制对象选项
if (this.plugin.settings.customizeTargets) {
new Setting(containerEl)
.setName(this.plugin.t('enable-inline-code'))
.setDesc(this.plugin.t('enable-inline-code-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enableInlineCode)
.onChange(async (value) => {
this.plugin.settings.enableInlineCode = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('enable-bold'))
.setDesc(this.plugin.t('enable-bold-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enableBold)
.onChange(async (value) => {
this.plugin.settings.enableBold = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('enable-highlight'))
.setDesc(this.plugin.t('enable-highlight-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enableHighlight)
.onChange(async (value) => {
this.plugin.settings.enableHighlight = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('enable-italic'))
.setDesc(this.plugin.t('enable-italic-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enableItalic)
.onChange(async (value) => {
this.plugin.settings.enableItalic = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('enable-strikethrough'))
.setDesc(this.plugin.t('enable-strikethrough-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enableStrikethrough)
.onChange(async (value) => {
this.plugin.settings.enableStrikethrough = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('enable-inline-latex'))
.setDesc(this.plugin.t('enable-inline-latex-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enableInlineLatex)
.onChange(async (value) => {
this.plugin.settings.enableInlineLatex = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName(this.plugin.t('enable-link'))
.setDesc(this.plugin.t('enable-link-desc'))
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enableLink)
.onChange(async (value) => {
this.plugin.settings.enableLink = value;
await this.plugin.saveSettings();
}));
}
}
}

55
src/type.ts Normal file
View file

@ -0,0 +1,55 @@
export enum LinkFormat {
MDLINK = 'markdown-link',
WIKILINK = 'wiki-link'
}
export enum ContextType {
NULL = 'null',
HEADING = 'heading',
INLINECODE = 'inline-code',
BOLD = 'bold',
ITALIC = 'italic',
HIGHLIGHT = 'highlight',
STRIKETHROUGH = 'strikethrough',
BLOCKID = 'block-id',
INLINELATEX = 'inline-latex',
LINKTITLE = 'link-title',
LINEURL = 'line-url',
}
export interface ContextData {
type: ContextType;
curLine: string;
match: string | null;
range: [number, number] | null;
}
export interface EasyCopySettings {
addToMenu: boolean;
showNotice: boolean;
useHeadingAsDisplayText: boolean;
linkFormat: LinkFormat;
customizeTargets: boolean;
enableInlineCode: boolean;
enableBold: boolean;
enableHighlight: boolean;
enableItalic: boolean;
enableStrikethrough: boolean;
enableInlineLatex: boolean;
enableLink: boolean;
}
export const DEFAULT_SETTINGS: EasyCopySettings = {
addToMenu: true,
showNotice: true,
useHeadingAsDisplayText: true,
linkFormat: LinkFormat.WIKILINK,
customizeTargets: false,
enableInlineCode: true,
enableBold: true,
enableHighlight: true,
enableItalic: true,
enableStrikethrough: true,
enableInlineLatex: true,
enableLink: true,
}