Skip to content

Commit 79b0e5e

Browse files
committed
Add commands to copy links and embeds
1 parent eeb6228 commit 79b0e5e

2 files changed

Lines changed: 138 additions & 74 deletions

File tree

main.ts

Lines changed: 137 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
import { EditorPosition, ListItemCache, Plugin, SectionCache } from "obsidian";
1+
import {
2+
Editor,
3+
EditorPosition,
4+
HeadingCache,
5+
ListItemCache,
6+
MarkdownView,
7+
Plugin,
8+
SectionCache,
9+
TFile,
10+
} from "obsidian";
211

312
function generateId(): string {
413
return Math.random().toString(36).substr(2, 6);
@@ -20,85 +29,23 @@ export default class MyPlugin extends Plugin {
2029
async onload() {
2130
this.registerEvent(
2231
this.app.workspace.on("editor-menu", (menu, editor, view) => {
23-
const cursor = editor.getCursor("to");
24-
const fileCache = this.app.metadataCache.getFileCache(view.file);
25-
26-
let blockCache: ListItemCache | SectionCache = (
27-
fileCache?.sections || []
28-
).find((section) => {
29-
return (
30-
section.position.start.line <= cursor.line &&
31-
section.position.end.line >= cursor.line
32-
);
33-
});
34-
35-
if (!blockCache) return;
32+
const block = this.getBlock(editor, view.file);
3633

37-
if (blockCache.type === "list") {
38-
blockCache = (fileCache?.listItems || []).find((item) => {
39-
return (
40-
item.position.start.line <= cursor.line &&
41-
item.position.end.line >= cursor.line
42-
);
43-
});
44-
}
34+
if (!block) return;
4535

46-
const isHeading = (blockCache as any).type === "heading";
36+
const isHeading = !!(block as any).heading;
4737

4838
const onClick = (isEmbed: boolean) => {
49-
// Copy heading
5039
if (isHeading) {
51-
const heading = fileCache.headings.find((heading) => {
52-
return (
53-
heading.position.start.line === blockCache.position.start.line
54-
);
55-
});
56-
57-
return (
58-
heading &&
59-
navigator.clipboard.writeText(
60-
`${
61-
isEmbed ? "!" : ""
62-
}${this.app.fileManager.generateMarkdownLink(
63-
view.file,
64-
"",
65-
"#" + heading.heading
66-
)}`
67-
)
68-
);
69-
}
70-
71-
const blockId = blockCache.id;
72-
73-
// Copy existing block id
74-
if (blockId) {
75-
return navigator.clipboard.writeText(
76-
`${isEmbed ? "!" : ""}${this.app.fileManager.generateMarkdownLink(
77-
view.file,
78-
"",
79-
"#^" + blockId
80-
)}`
40+
this.handleHeading(view.file, block as HeadingCache, isEmbed);
41+
} else {
42+
this.handleBlock(
43+
view.file,
44+
editor,
45+
block as SectionCache | ListItemCache,
46+
isEmbed
8147
);
8248
}
83-
84-
// Add a block id
85-
const sectionEnd = blockCache.position.end;
86-
const end: EditorPosition = {
87-
ch: sectionEnd.col,
88-
line: sectionEnd.line,
89-
};
90-
91-
const id = generateId();
92-
const spacer = shouldInsertAfter(blockCache) ? "\n\n" : " ";
93-
94-
editor.replaceRange(`${spacer}^${id}`, end);
95-
navigator.clipboard.writeText(
96-
`${isEmbed ? "!" : ""}${this.app.fileManager.generateMarkdownLink(
97-
view.file,
98-
"",
99-
"#^" + id
100-
)}`
101-
);
10249
};
10350

10451
menu.addItem((item) => {
@@ -116,5 +63,122 @@ export default class MyPlugin extends Plugin {
11663
});
11764
})
11865
);
66+
67+
this.addCommand({
68+
id: 'copy-link-to-block',
69+
name: "Copy link to current block or heading",
70+
editorCheckCallback: (isChecking, editor, view) => {
71+
return this.handleCommand(isChecking, editor, view, false)
72+
},
73+
})
74+
75+
this.addCommand({
76+
id: 'copy-embed-to-block',
77+
name: "Copy embed to current block or heading",
78+
editorCheckCallback: (isChecking, editor, view) => {
79+
return this.handleCommand(isChecking, editor, view, true)
80+
},
81+
})
82+
}
83+
84+
handleCommand(isChecking: boolean, editor: Editor, view: MarkdownView, isEmbed: boolean) {
85+
if (isChecking) {
86+
return !!this.getBlock(editor, view.file);
87+
}
88+
89+
const block = this.getBlock(editor, view.file);
90+
91+
if (!block) return;
92+
93+
const isHeading = !!(block as any).heading;
94+
95+
if (isHeading) {
96+
this.handleHeading(view.file, block as HeadingCache, isEmbed);
97+
} else {
98+
this.handleBlock(
99+
view.file,
100+
editor,
101+
block as SectionCache | ListItemCache,
102+
isEmbed
103+
);
104+
}
105+
}
106+
107+
getBlock(editor: Editor, file: TFile) {
108+
const cursor = editor.getCursor("to");
109+
const fileCache = this.app.metadataCache.getFileCache(file);
110+
111+
let block: ListItemCache | HeadingCache | SectionCache = (
112+
fileCache?.sections || []
113+
).find((section) => {
114+
return (
115+
section.position.start.line <= cursor.line &&
116+
section.position.end.line >= cursor.line
117+
);
118+
});
119+
120+
if (block?.type === "list") {
121+
block = (fileCache?.listItems || []).find((item) => {
122+
return (
123+
item.position.start.line <= cursor.line &&
124+
item.position.end.line >= cursor.line
125+
);
126+
});
127+
} else if (block?.type === "heading") {
128+
block = fileCache.headings.find((heading) => {
129+
return heading.position.start.line === block.position.start.line;
130+
});
131+
}
132+
133+
return block
134+
}
135+
136+
handleHeading(file: TFile, block: HeadingCache, isEmbed: boolean) {
137+
navigator.clipboard.writeText(
138+
`${isEmbed ? "!" : ""}${this.app.fileManager.generateMarkdownLink(
139+
file,
140+
"",
141+
"#" + block.heading
142+
)}`
143+
);
144+
}
145+
146+
handleBlock(
147+
file: TFile,
148+
editor: Editor,
149+
block: ListItemCache | SectionCache,
150+
isEmbed: boolean
151+
) {
152+
const blockId = block.id;
153+
154+
// Copy existing block id
155+
if (blockId) {
156+
return navigator.clipboard.writeText(
157+
`${isEmbed ? "!" : ""}${this.app.fileManager.generateMarkdownLink(
158+
file,
159+
"",
160+
"#^" + blockId
161+
)}`
162+
);
163+
}
164+
165+
// Add a block id
166+
const sectionEnd = block.position.end;
167+
const end: EditorPosition = {
168+
ch: sectionEnd.col,
169+
line: sectionEnd.line,
170+
};
171+
172+
const id = generateId();
173+
const spacer = shouldInsertAfter(block) ? "\n\n" : " ";
174+
175+
editor.replaceRange(`${spacer}^${id}`, end);
176+
navigator.clipboard.writeText(
177+
`${isEmbed ? "!" : ""}${this.app.fileManager.generateMarkdownLink(
178+
file,
179+
"",
180+
"#^" + id
181+
)}`
182+
);
119183
}
120184
}

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "obsidian-copy-block-link",
33
"name": "Copy Block Link",
4-
"version": "1.0.1",
4+
"version": "1.0.2",
55
"minAppVersion": "0.12.12",
66
"description": "Get links to blocks and headings from Obsidian's right click menu",
77
"author": "mgmeyers",

0 commit comments

Comments
 (0)