forked from manic/obsidian-wrap-with-shortcuts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.ts
110 lines (93 loc) · 3.31 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { MarkdownView, Plugin, EditorPosition, Command } from "obsidian";
import SettingsTab from './src/SettingsTab'
export interface WrapperTag {
name: string;
startTag: string;
endTag: string;
}
interface WrapperTagSettings {
wrapperTags: WrapperTag[];
}
const DEFAULT_SETTINGS: WrapperTagSettings = {
wrapperTags: [
{
name: 'Underline',
startTag: '<u>',
endTag: '</u>'
},
]
}
export default class WrapWithShortcut extends Plugin {
settings: WrapperTagSettings;
async onload() {
await this.loadSettings();
this.settings.wrapperTags.forEach((wrapperTag, index) => {
const command: Command = {
id: `wrap-with-shortcut-${index}`,
name: `Toggle ${wrapperTag.name}`,
callback: () => this.wrapSelectedTextIn(wrapperTag.startTag, wrapperTag.endTag),
};
this.addCommand(command);
});
this.addSettingTab(new SettingsTab(this));
}
wrapSelectedTextIn(startTag = '<u>', endTag = '</u>'): void {
const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView);
if (!markdownView) {
return;
}
if (startTag === '' || endTag === '') {
return;
}
const editor = markdownView.editor;
const selectedText = editor.somethingSelected() ? editor.getSelection() : "";
function toPos(pos: number): EditorPosition {
return editor.offsetToPos(pos);
}
function getRange(from: number, to: number): string {
try {
return editor.getRange(toPos(from), toPos(to));
} catch (_) {
return '';
}
}
/* Detect whether the selected text is packed by <u></u>.
If true, unpack it, else pack with <u></u>. */
const fos = editor.posToOffset(editor.getCursor("from")); // from offset
const tos = editor.posToOffset(editor.getCursor("to")); // to offset
const len = selectedText.length;
const beforeText = getRange(fos - startTag.length, tos - len);
const afterText = getRange(fos + len, tos + endTag.length);
const startText = getRange(fos, fos + startTag.length);
const endText = getRange(tos - endTag.length, tos);
if (beforeText === startTag && afterText === endTag) {
//=> undo (inside selection)
editor.setSelection(toPos(fos - startTag.length), toPos(tos + endTag.length));
editor.replaceSelection(`${selectedText}`);
// re-select
editor.setSelection(toPos(fos - startTag.length), toPos(tos - startTag.length));
} else if (startText === startTag && endText === endTag) {
//=> undo (outside selection)
editor.replaceSelection(editor.getRange(toPos(fos + startTag.length), toPos(tos - endTag.length)));
// re-select
editor.setSelection(toPos(fos), toPos(tos - (startTag.length + endTag.length)));
} else {
//=> do wrap
if (selectedText) {
editor.replaceSelection(`${startTag}${selectedText}${endTag}`);
editor.setSelection(toPos(fos + startTag.length), toPos(tos + startTag.length));
} else {
editor.replaceSelection(`${startTag}${endTag}`);
const cursor = editor.getCursor();
cursor.ch -= endTag.length;
editor.setCursor(cursor);
}
}
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
}
}